├── .deepsource.toml ├── .gitignore ├── AUTHORS ├── COPYING ├── README.md ├── benchmarks_test.go ├── binary_test.go ├── circle.yml ├── codecov.yml ├── conversion.go ├── conversion_fuzz_test.go ├── conversion_test.go ├── decimal.go ├── decimal_test.go ├── div.go ├── go.mod ├── mod.go ├── oss-fuzz.sh ├── shared_test.go ├── ternary_test.go ├── uint256.go ├── uint256_test.go └── unary_test.go /.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"] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | 3 | 4 | # go output files 5 | *.test 6 | *.out 7 | *.pb.gz 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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)) 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 benchmark_Lsh_Big(n uint, bench *testing.B) { 437 | original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) 438 | bench.ResetTimer() 439 | for i := 0; i < bench.N; i++ { 440 | b1 := big.NewInt(0) 441 | b1.Lsh(original, n) 442 | } 443 | } 444 | func benchmark_Lsh_Big_N_EQ_0(bench *testing.B) { 445 | benchmark_Lsh_Big(0, bench) 446 | } 447 | func benchmark_Lsh_Big_N_GT_192(bench *testing.B) { 448 | benchmark_Lsh_Big(193, bench) 449 | } 450 | func benchmark_Lsh_Big_N_GT_128(bench *testing.B) { 451 | benchmark_Lsh_Big(129, bench) 452 | } 453 | func benchmark_Lsh_Big_N_GT_64(bench *testing.B) { 454 | benchmark_Lsh_Big(65, bench) 455 | } 456 | func benchmark_Lsh_Big_N_GT_0(bench *testing.B) { 457 | benchmark_Lsh_Big(1, bench) 458 | } 459 | func benchmark_Lsh_Bit(n uint, bench *testing.B) { 460 | original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) 461 | f2, _ := FromBig(original) 462 | bench.ResetTimer() 463 | for i := 0; i < bench.N; i++ { 464 | f1 := new(Int) 465 | f1.Lsh(f2, n) 466 | } 467 | } 468 | func benchmark_Lsh_Bit_N_EQ_0(bench *testing.B) { 469 | benchmark_Lsh_Bit(0, bench) 470 | } 471 | func benchmark_Lsh_Bit_N_GT_192(bench *testing.B) { 472 | benchmark_Lsh_Bit(193, bench) 473 | } 474 | func benchmark_Lsh_Bit_N_GT_128(bench *testing.B) { 475 | benchmark_Lsh_Bit(129, bench) 476 | } 477 | func benchmark_Lsh_Bit_N_GT_64(bench *testing.B) { 478 | benchmark_Lsh_Bit(65, bench) 479 | } 480 | func benchmark_Lsh_Bit_N_GT_0(bench *testing.B) { 481 | benchmark_Lsh_Bit(1, bench) 482 | } 483 | func BenchmarkLsh(bench *testing.B) { 484 | bench.Run("n_eq_0/big", benchmark_Lsh_Big_N_EQ_0) 485 | bench.Run("n_gt_192/big", benchmark_Lsh_Big_N_GT_192) 486 | bench.Run("n_gt_128/big", benchmark_Lsh_Big_N_GT_128) 487 | bench.Run("n_gt_64/big", benchmark_Lsh_Big_N_GT_64) 488 | bench.Run("n_gt_0/big", benchmark_Lsh_Big_N_GT_0) 489 | 490 | bench.Run("n_eq_0/uint256", benchmark_Lsh_Bit_N_EQ_0) 491 | bench.Run("n_gt_192/uint256", benchmark_Lsh_Bit_N_GT_192) 492 | bench.Run("n_gt_128/uint256", benchmark_Lsh_Bit_N_GT_128) 493 | bench.Run("n_gt_64/uint256", benchmark_Lsh_Bit_N_GT_64) 494 | bench.Run("n_gt_0/uint256", benchmark_Lsh_Bit_N_GT_0) 495 | } 496 | 497 | func benchmark_Rsh_Big(n uint, bench *testing.B) { 498 | original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) 499 | bench.ResetTimer() 500 | for i := 0; i < bench.N; i++ { 501 | b1 := big.NewInt(0) 502 | b1.Rsh(original, n) 503 | } 504 | } 505 | func benchmark_Rsh_Big_N_EQ_0(bench *testing.B) { 506 | benchmark_Rsh_Big(0, bench) 507 | } 508 | func benchmark_Rsh_Big_N_GT_192(bench *testing.B) { 509 | benchmark_Rsh_Big(193, bench) 510 | } 511 | func benchmark_Rsh_Big_N_GT_128(bench *testing.B) { 512 | benchmark_Rsh_Big(129, bench) 513 | } 514 | func benchmark_Rsh_Big_N_GT_64(bench *testing.B) { 515 | benchmark_Rsh_Big(65, bench) 516 | } 517 | func benchmark_Rsh_Big_N_GT_0(bench *testing.B) { 518 | benchmark_Rsh_Big(1, bench) 519 | } 520 | func benchmark_Rsh_Bit(n uint, bench *testing.B) { 521 | original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) 522 | f2, _ := FromBig(original) 523 | bench.ResetTimer() 524 | for i := 0; i < bench.N; i++ { 525 | f1 := new(Int) 526 | f1.Rsh(f2, n) 527 | } 528 | } 529 | func benchmark_Rsh_Bit_N_EQ_0(bench *testing.B) { 530 | benchmark_Rsh_Bit(0, bench) 531 | } 532 | func benchmark_Rsh_Bit_N_GT_192(bench *testing.B) { 533 | benchmark_Rsh_Bit(193, bench) 534 | } 535 | func benchmark_Rsh_Bit_N_GT_128(bench *testing.B) { 536 | benchmark_Rsh_Bit(129, bench) 537 | } 538 | func benchmark_Rsh_Bit_N_GT_64(bench *testing.B) { 539 | benchmark_Rsh_Bit(65, bench) 540 | } 541 | func benchmark_Rsh_Bit_N_GT_0(bench *testing.B) { 542 | benchmark_Rsh_Bit(1, bench) 543 | } 544 | func BenchmarkRsh(bench *testing.B) { 545 | bench.Run("n_eq_0/big", benchmark_Rsh_Big_N_EQ_0) 546 | bench.Run("n_gt_192/big", benchmark_Rsh_Big_N_GT_192) 547 | bench.Run("n_gt_128/big", benchmark_Rsh_Big_N_GT_128) 548 | bench.Run("n_gt_64/big", benchmark_Rsh_Big_N_GT_64) 549 | bench.Run("n_gt_0/big", benchmark_Rsh_Big_N_GT_0) 550 | 551 | bench.Run("n_eq_0/uint256", benchmark_Rsh_Bit_N_EQ_0) 552 | bench.Run("n_gt_192/uint256", benchmark_Rsh_Bit_N_GT_192) 553 | bench.Run("n_gt_128/uint256", benchmark_Rsh_Bit_N_GT_128) 554 | bench.Run("n_gt_64/uint256", benchmark_Rsh_Bit_N_GT_64) 555 | bench.Run("n_gt_0/uint256", benchmark_Rsh_Bit_N_GT_0) 556 | } 557 | 558 | // bigExp implements exponentiation by squaring. 559 | // The result is truncated to 256 bits. 560 | func bigExp(result, base, exponent *big.Int) *big.Int { 561 | result.SetUint64(1) 562 | 563 | for _, word := range exponent.Bits() { 564 | for i := 0; i < wordBits; i++ { 565 | if word&1 == 1 { 566 | bigU256(result.Mul(result, base)) 567 | } 568 | bigU256(base.Mul(base, base)) 569 | word >>= 1 570 | } 571 | } 572 | return result 573 | } 574 | 575 | func benchmark_Exp_Big(bench *testing.B, x, y string) { 576 | orig := big.NewInt(0).SetBytes(hex2Bytes(x)) 577 | base := big.NewInt(0).SetBytes(hex2Bytes(x)) 578 | exp := big.NewInt(0).SetBytes(hex2Bytes(y)) 579 | 580 | result := new(big.Int) 581 | bench.ResetTimer() 582 | for i := 0; i < bench.N; i++ { 583 | bigExp(result, base, exp) 584 | base.Set(orig) 585 | } 586 | } 587 | 588 | func benchmark_Exp_U256(bench *testing.B, x, y string) { 589 | var ( 590 | base = big.NewInt(0).SetBytes(hex2Bytes(x)) 591 | exp = big.NewInt(0).SetBytes(hex2Bytes(y)) 592 | 593 | f_base, _ = FromBig(base) 594 | f_orig, _ = FromBig(base) 595 | f_exp, _ = FromBig(exp) 596 | f_res Int 597 | ) 598 | bench.ResetTimer() 599 | for i := 0; i < bench.N; i++ { 600 | f_res.Exp(f_base, f_exp) 601 | f_base.Set(f_orig) 602 | } 603 | } 604 | 605 | func BenchmarkExp(bench *testing.B) { 606 | { // Large values 607 | base := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" 608 | exp := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" 609 | bench.Run("large/big", func(b *testing.B) { 610 | benchmark_Exp_Big(b, base, exp) 611 | }) 612 | bench.Run("large/uint256", func(b *testing.B) { 613 | benchmark_Exp_U256(b, base, exp) 614 | }) 615 | } 616 | { // Smaller exponent 617 | base := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" 618 | exp := "8abcdef" 619 | bench.Run("small/big", func(b *testing.B) { 620 | benchmark_Exp_Big(b, base, exp) 621 | }) 622 | bench.Run("small/uint256", func(b *testing.B) { 623 | benchmark_Exp_U256(b, base, exp) 624 | }) 625 | } 626 | { // Even base (and very small exponent) 627 | base := "ABCDEF090807060504030201fffffffffffffffffffffffffffffffffffffffe" 628 | exp := "ff" 629 | bench.Run("even/big", func(b *testing.B) { 630 | benchmark_Exp_Big(b, base, exp) 631 | }) 632 | bench.Run("even/uint256", func(b *testing.B) { 633 | benchmark_Exp_U256(b, base, exp) 634 | }) 635 | } 636 | } 637 | 638 | func BenchmarkDiv(b *testing.B) { 639 | benchmarkDivUint256 := func(b *testing.B, xSamples, modSamples *[numSamples]Int) { 640 | var sink Int 641 | for j := 0; j < b.N; j += numSamples { 642 | for i := 0; i < numSamples; i++ { 643 | sink.Div(&xSamples[i], &modSamples[i]) 644 | } 645 | } 646 | } 647 | benchmarkDivBig := func(b *testing.B, xSamples, modSamples *[numSamples]big.Int) { 648 | var sink big.Int 649 | for j := 0; j < b.N; j += numSamples { 650 | for i := 0; i < numSamples; i++ { 651 | sink.Div(&xSamples[i], &modSamples[i]) 652 | } 653 | } 654 | } 655 | 656 | b.Run("small/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int32Samples, &int32SamplesLt) }) 657 | b.Run("mod64/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int64Samples) }) 658 | b.Run("mod128/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int128Samples) }) 659 | b.Run("mod192/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int192Samples) }) 660 | b.Run("mod256/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int256SamplesLt) }) 661 | b.Run("small/big", func(b *testing.B) { benchmarkDivBig(b, &big32Samples, &big32SamplesLt) }) 662 | b.Run("mod64/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big64Samples) }) 663 | b.Run("mod128/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big128Samples) }) 664 | b.Run("mod192/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big192Samples) }) 665 | b.Run("mod256/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big256SamplesLt) }) 666 | } 667 | 668 | func BenchmarkMod(b *testing.B) { 669 | benchmarkModUint256 := 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.Mod(&xSamples[i], &modSamples[i]) 674 | } 675 | } 676 | } 677 | benchmarkModBig := 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.Mod(&xSamples[i], &modSamples[i]) 682 | } 683 | } 684 | } 685 | 686 | b.Run("small/uint256", func(b *testing.B) { benchmarkModUint256(b, &int32Samples, &int32SamplesLt) }) 687 | b.Run("mod64/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int64Samples) }) 688 | b.Run("mod128/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int128Samples) }) 689 | b.Run("mod192/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int192Samples) }) 690 | b.Run("mod256/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int256SamplesLt) }) 691 | b.Run("small/big", func(b *testing.B) { benchmarkModBig(b, &big32Samples, &big32SamplesLt) }) 692 | b.Run("mod64/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big64Samples) }) 693 | b.Run("mod128/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big128Samples) }) 694 | b.Run("mod192/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big192Samples) }) 695 | b.Run("mod256/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big256SamplesLt) }) 696 | } 697 | 698 | func BenchmarkDivMod(b *testing.B) { 699 | benchmarkDivModUint256 := func(b *testing.B, xSamples, modSamples *[numSamples]Int) { 700 | var sink, mod Int 701 | for j := 0; j < b.N; j += numSamples { 702 | for i := 0; i < numSamples; i++ { 703 | sink.DivMod(&xSamples[i], &modSamples[i], &mod) 704 | } 705 | } 706 | } 707 | benchmarkDivModBig := func(b *testing.B, xSamples, modSamples *[numSamples]big.Int) { 708 | var sink, mod big.Int 709 | for j := 0; j < b.N; j += numSamples { 710 | for i := 0; i < numSamples; i++ { 711 | sink.DivMod(&xSamples[i], &modSamples[i], &mod) 712 | } 713 | } 714 | } 715 | 716 | b.Run("small/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int32Samples, &int32SamplesLt) }) 717 | b.Run("mod64/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int64Samples) }) 718 | b.Run("mod128/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int128Samples) }) 719 | b.Run("mod192/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int192Samples) }) 720 | b.Run("mod256/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int256SamplesLt) }) 721 | b.Run("small/big", func(b *testing.B) { benchmarkDivModBig(b, &big32Samples, &big32SamplesLt) }) 722 | b.Run("mod64/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big64Samples) }) 723 | b.Run("mod128/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big128Samples) }) 724 | b.Run("mod192/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big192Samples) }) 725 | b.Run("mod256/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big256SamplesLt) }) 726 | } 727 | 728 | func BenchmarkAddMod(b *testing.B) { 729 | benchmarkAddModUint256 := func(b *testing.B, factorsSamples, modSamples *[numSamples]Int) { 730 | iter := (b.N + numSamples - 1) / numSamples 731 | 732 | for j := 0; j < numSamples; j++ { 733 | var x Int 734 | y := factorsSamples[j] 735 | 736 | for i := 0; i < iter; i++ { 737 | x.AddMod(&x, &y, &modSamples[j]) 738 | } 739 | } 740 | } 741 | benchmarkAddModBig := func(b *testing.B, factorsSamples, modSamples *[numSamples]big.Int) { 742 | iter := (b.N + numSamples - 1) / numSamples 743 | 744 | for j := 0; j < numSamples; j++ { 745 | var x big.Int 746 | y := factorsSamples[j] 747 | 748 | for i := 0; i < iter; i++ { 749 | x.Add(&x, &y) 750 | x.Mod(&x, &modSamples[j]) 751 | } 752 | } 753 | } 754 | 755 | b.Run("small/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int32SamplesLt, &int32Samples) }) 756 | b.Run("mod64/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int64SamplesLt, &int64Samples) }) 757 | b.Run("mod128/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int128SamplesLt, &int128Samples) }) 758 | b.Run("mod192/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int192SamplesLt, &int192Samples) }) 759 | b.Run("mod256/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int256SamplesLt, &int256Samples) }) 760 | b.Run("small/big", func(b *testing.B) { benchmarkAddModBig(b, &big32SamplesLt, &big32Samples) }) 761 | b.Run("mod64/big", func(b *testing.B) { benchmarkAddModBig(b, &big64SamplesLt, &big64Samples) }) 762 | b.Run("mod128/big", func(b *testing.B) { benchmarkAddModBig(b, &big128SamplesLt, &big128Samples) }) 763 | b.Run("mod192/big", func(b *testing.B) { benchmarkAddModBig(b, &big192SamplesLt, &big192Samples) }) 764 | b.Run("mod256/big", func(b *testing.B) { benchmarkAddModBig(b, &big256SamplesLt, &big256Samples) }) 765 | } 766 | 767 | func BenchmarkMulMod(b *testing.B) { 768 | benchmarkMulModUint256R := func(b *testing.B, factorsSamples, modSamples *[numSamples]Int) { 769 | iter := (b.N + numSamples - 1) / numSamples 770 | 771 | var mu [numSamples][5]uint64 772 | 773 | for i := 0; i < numSamples; i++ { 774 | mu[i] = Reciprocal(&modSamples[i]) 775 | } 776 | 777 | b.ResetTimer() 778 | 779 | for j := 0; j < numSamples; j++ { 780 | x := factorsSamples[j] 781 | 782 | for i := 0; i < iter; i++ { 783 | x.MulModWithReciprocal(&x, &factorsSamples[j], &modSamples[j], &mu[j]) 784 | } 785 | } 786 | } 787 | benchmarkMulModUint256 := func(b *testing.B, factorsSamples, modSamples *[numSamples]Int) { 788 | iter := (b.N + numSamples - 1) / numSamples 789 | 790 | for j := 0; j < numSamples; j++ { 791 | x := factorsSamples[j] 792 | 793 | for i := 0; i < iter; i++ { 794 | x.MulMod(&x, &factorsSamples[j], &modSamples[j]) 795 | } 796 | } 797 | } 798 | benchmarkMulModBig := func(b *testing.B, factorsSamples, modSamples *[numSamples]big.Int) { 799 | iter := (b.N + numSamples - 1) / numSamples 800 | 801 | for j := 0; j < numSamples; j++ { 802 | x := factorsSamples[j] 803 | 804 | for i := 0; i < iter; i++ { 805 | x.Mul(&x, &factorsSamples[j]) 806 | x.Mod(&x, &modSamples[j]) 807 | } 808 | } 809 | } 810 | 811 | b.Run("small/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int32SamplesLt, &int32Samples) }) 812 | b.Run("mod64/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int64SamplesLt, &int64Samples) }) 813 | b.Run("mod128/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int128SamplesLt, &int128Samples) }) 814 | b.Run("mod192/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int192SamplesLt, &int192Samples) }) 815 | b.Run("mod256/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int256SamplesLt, &int256Samples) }) 816 | b.Run("mod256/uint256r", func(b *testing.B) { benchmarkMulModUint256R(b, &int256SamplesLt, &int256Samples) }) 817 | b.Run("small/big", func(b *testing.B) { benchmarkMulModBig(b, &big32SamplesLt, &big32Samples) }) 818 | b.Run("mod64/big", func(b *testing.B) { benchmarkMulModBig(b, &big64SamplesLt, &big64Samples) }) 819 | b.Run("mod128/big", func(b *testing.B) { benchmarkMulModBig(b, &big128SamplesLt, &big128Samples) }) 820 | b.Run("mod192/big", func(b *testing.B) { benchmarkMulModBig(b, &big192SamplesLt, &big192Samples) }) 821 | b.Run("mod256/big", func(b *testing.B) { benchmarkMulModBig(b, &big256SamplesLt, &big256Samples) }) 822 | } 823 | 824 | func benchmark_SdivLarge_Big(bench *testing.B) { 825 | a := new(big.Int).SetBytes(hex2Bytes("800fffffffffffffffffffffffffd1e870eec79504c60144cc7f5fc2bad1e611")) 826 | b := new(big.Int).SetBytes(hex2Bytes("ff3f9014f20db29ae04af2c2d265de17")) 827 | 828 | bench.ResetTimer() 829 | 830 | for i := 0; i < bench.N; i++ { 831 | bigU256(bigSDiv(new(big.Int), a, b)) 832 | } 833 | } 834 | 835 | func benchmark_SdivLarge_Bit(bench *testing.B) { 836 | a := big.NewInt(0).SetBytes(hex2Bytes("800fffffffffffffffffffffffffd1e870eec79504c60144cc7f5fc2bad1e611")) 837 | b := big.NewInt(0).SetBytes(hex2Bytes("ff3f9014f20db29ae04af2c2d265de17")) 838 | fa, _ := FromBig(a) 839 | fb, _ := FromBig(b) 840 | 841 | bench.ResetTimer() 842 | for i := 0; i < bench.N; i++ { 843 | f := new(Int) 844 | f.SDiv(fa, fb) 845 | } 846 | } 847 | 848 | func BenchmarkSDiv(bench *testing.B) { 849 | bench.Run("large/big", benchmark_SdivLarge_Big) 850 | bench.Run("large/uint256", benchmark_SdivLarge_Bit) 851 | } 852 | 853 | func BenchmarkEncodeHex(b *testing.B) { 854 | hexEncodeU256 := func(b *testing.B, samples *[numSamples]Int) { 855 | b.ReportAllocs() 856 | for j := 0; j < b.N; j += numSamples { 857 | for i := 0; i < numSamples; i++ { 858 | samples[i].Hex() 859 | } 860 | } 861 | } 862 | hexEncodeBig := func(b *testing.B, samples *[numSamples]big.Int) { 863 | b.ReportAllocs() 864 | for j := 0; j < b.N; j += numSamples { 865 | for i := 0; i < numSamples; i++ { 866 | // We're being nice to big.Int here, because this method 867 | // does not add the 0x-prefix -- so an extra alloc is needed to get 868 | // the same result. We still win the benchmark though... 869 | samples[i].Text(16) 870 | } 871 | } 872 | } 873 | b.Run("large/uint256", func(b *testing.B) { hexEncodeU256(b, &int256Samples) }) 874 | b.Run("large/big", func(b *testing.B) { hexEncodeBig(b, &big256Samples) }) 875 | } 876 | 877 | func BenchmarkFromHexString(b *testing.B) { 878 | var hexStrings []string 879 | for _, z := range &int256Samples { 880 | hexStrings = append(hexStrings, (&z).Hex()) 881 | } 882 | b.Run("uint256", func(b *testing.B) { 883 | b.ReportAllocs() 884 | for j := 0; j < b.N; j++ { 885 | i := j % numSamples 886 | if _, err := FromHex(hexStrings[i]); err != nil { 887 | b.Fatalf("%v: %v", err, string(hexStrings[i])) 888 | } 889 | } 890 | }) 891 | b.Run("big", func(b *testing.B) { 892 | b.ReportAllocs() 893 | for j := 0; j < b.N; j++ { 894 | i := j % numSamples 895 | if _, ok := big.NewInt(0).SetString(hexStrings[i], 0); !ok { 896 | b.Fatalf("Error on %v", string(hexStrings[i])) 897 | } 898 | } 899 | }) 900 | } 901 | 902 | func BenchmarkMulDivOverflow(b *testing.B) { 903 | benchmarkUint256 := func(b *testing.B, factorsSamples, muldivSamples *[numSamples]Int) { 904 | iter := (b.N + numSamples - 1) / numSamples 905 | 906 | for j := 0; j < numSamples; j++ { 907 | x := factorsSamples[j] 908 | 909 | for i := 0; i < iter; i++ { 910 | res := new(Int) 911 | res.MulDivOverflow(&x, &x, &muldivSamples[j]) 912 | } 913 | } 914 | } 915 | 916 | benchmarkBig := func(b *testing.B, factorsSamples, muldivSamples *[numSamples]big.Int) { 917 | iter := (b.N + numSamples - 1) / numSamples 918 | 919 | for j := 0; j < numSamples; j++ { 920 | x := factorsSamples[j] 921 | 922 | for i := 0; i < iter; i++ { 923 | res := new(big.Int) 924 | res.Mul(&x, &x) 925 | res.Div(res, &muldivSamples[j]) 926 | } 927 | } 928 | } 929 | 930 | b.Run("small/uint256", func(b *testing.B) { benchmarkUint256(b, &int32SamplesLt, &int32Samples) }) 931 | b.Run("div64/uint256", func(b *testing.B) { benchmarkUint256(b, &int64SamplesLt, &int64Samples) }) 932 | b.Run("div128/uint256", func(b *testing.B) { benchmarkUint256(b, &int128SamplesLt, &int128Samples) }) 933 | b.Run("div192/uint256", func(b *testing.B) { benchmarkUint256(b, &int192SamplesLt, &int192Samples) }) 934 | b.Run("div256/uint256", func(b *testing.B) { benchmarkUint256(b, &int256SamplesLt, &int256Samples) }) 935 | b.Run("small/big", func(b *testing.B) { benchmarkBig(b, &big32SamplesLt, &big32Samples) }) 936 | b.Run("div64/big", func(b *testing.B) { benchmarkBig(b, &big64SamplesLt, &big64Samples) }) 937 | b.Run("div128/big", func(b *testing.B) { benchmarkBig(b, &big128SamplesLt, &big128Samples) }) 938 | b.Run("div192/big", func(b *testing.B) { benchmarkBig(b, &big192SamplesLt, &big192Samples) }) 939 | b.Run("div256/big", func(b *testing.B) { benchmarkBig(b, &big256SamplesLt, &big256Samples) }) 940 | 941 | } 942 | 943 | func BenchmarkHashTreeRoot(b *testing.B) { 944 | var ( 945 | z = &Int{1, 2, 3, 4} 946 | 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} 947 | ) 948 | b.ReportAllocs() 949 | for i := 0; i < b.N; i++ { 950 | r, err := z.HashTreeRoot() 951 | if err != nil { 952 | b.Fatal(err) 953 | } 954 | if r != exp { 955 | b.Fatalf("have %v want %v", r, exp) 956 | } 957 | } 958 | } 959 | 960 | func BenchmarkSet(bench *testing.B) { 961 | benchmarkUint256 := func(bench *testing.B) { 962 | a := new(Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 963 | 964 | result := new(Int) 965 | bench.ResetTimer() 966 | for i := 0; i < bench.N; i++ { 967 | result.Set(a) 968 | } 969 | } 970 | benchmarkBig := func(bench *testing.B) { 971 | a := new(big.Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 972 | 973 | result := new(big.Int) 974 | bench.ResetTimer() 975 | for i := 0; i < bench.N; i++ { 976 | result.Set(a) 977 | } 978 | } 979 | 980 | bench.Run("single/uint256", benchmarkUint256) 981 | bench.Run("single/big", benchmarkBig) 982 | } 983 | 984 | func BenchmarkByte(bench *testing.B) { 985 | var ( 986 | a = new(Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 987 | num = NewInt(0) 988 | result = new(Int) 989 | ) 990 | bench.ResetTimer() 991 | for i := 0; i < bench.N; i++ { 992 | for ii := uint64(0); ii < 32; ii++ { 993 | result.Set(a) 994 | num.SetUint64(ii) 995 | _ = result.Byte(num) 996 | } 997 | } 998 | } 999 | 1000 | func BenchmarkExtendSign(b *testing.B) { 1001 | a, err := FromHex("0xf123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9") 1002 | if err != nil { 1003 | b.Fatal(err) 1004 | } 1005 | result := new(Int) 1006 | n := NewInt(0) 1007 | b.ResetTimer() 1008 | for i := uint64(0); i < uint64(b.N); i++ { 1009 | n.SetUint64(i % 33) 1010 | result.ExtendSign(a, n) 1011 | } 1012 | } 1013 | 1014 | func BenchmarkWriteTo(b *testing.B) { 1015 | fa, err := FromHex("0x1100030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611") 1016 | if err != nil { 1017 | b.Fatal(err) 1018 | } 1019 | b.Run("fixed-20", func(b *testing.B) { 1020 | dest := [20]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 1021 | for i := 0; i < b.N; i++ { 1022 | fa.WriteToArray20(&dest) 1023 | } 1024 | _ = (string(dest[:])) // Prevent the compiler from optimizing away the op 1025 | }) 1026 | b.Run("fixed-32", func(b *testing.B) { 1027 | 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} 1028 | for i := 0; i < b.N; i++ { 1029 | fa.WriteToArray32(&dest) 1030 | } 1031 | _ = (string(dest[:])) // Prevent the compiler from optimizing away the op 1032 | }) 1033 | b.Run("slice", func(b *testing.B) { 1034 | dest := make([]byte, 64) 1035 | for i := 0; i < b.N; i++ { 1036 | fa.WriteToSlice(dest) 1037 | } 1038 | _ = (string(dest[:])) // Prevent the compiler from optimizing away the op 1039 | }) 1040 | b.Run("put256", func(b *testing.B) { 1041 | dest := make([]byte, 64) 1042 | for i := 0; i < b.N; i++ { 1043 | fa.PutUint256(dest) 1044 | } 1045 | _ = (string(dest[:])) // Prevent the compiler from optimizing away the op 1046 | }) 1047 | } 1048 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | // SetBytes16 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/holiman/uint256 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 divModZ(z, x, y, m *Int) *Int { 127 | z2, _ := z.DivMod(x, y, m) 128 | return z2 129 | } 130 | 131 | func bigDivModZ(result, x, y, mod *big.Int) *big.Int { 132 | if y.Sign() == 0 { 133 | return result.SetUint64(0) 134 | } 135 | z2, _ := result.DivMod(x, y, mod) 136 | return z2 137 | } 138 | 139 | func divModM(z, x, y, m *Int) *Int { 140 | _, m2 := z.DivMod(x, y, m) 141 | return z.Set(m2) 142 | } 143 | 144 | func bigDivModM(result, x, y, mod *big.Int) *big.Int { 145 | if y.Sign() == 0 { 146 | return result.SetUint64(0) 147 | } 148 | _, m2 := result.DivMod(x, y, mod) 149 | return result.Set(m2) 150 | } 151 | -------------------------------------------------------------------------------- /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 | for i := 0; i <= end; i++ { 143 | dest[end-i] = byte(z[i/8] >> uint64(8*(i%8))) 144 | } 145 | } 146 | 147 | // PutUint256 writes all 32 bytes of z to the destination slice, including zero-bytes. 148 | // If dest is larger than 32 bytes, z will fill the first parts, and leave 149 | // the end untouched. 150 | // Note: The dest slice must be at least 32 bytes large, otherwise this 151 | // method will panic. The method WriteToSlice, which is slower, should be used 152 | // if the destination slice is smaller or of unknown size. 153 | func (z *Int) PutUint256(dest []byte) { 154 | _ = dest[31] 155 | binary.BigEndian.PutUint64(dest[0:8], z[3]) 156 | binary.BigEndian.PutUint64(dest[8:16], z[2]) 157 | binary.BigEndian.PutUint64(dest[16:24], z[1]) 158 | binary.BigEndian.PutUint64(dest[24:32], z[0]) 159 | } 160 | 161 | // WriteToArray32 writes all 32 bytes of z to the destination array, including zero-bytes 162 | func (z *Int) WriteToArray32(dest *[32]byte) { 163 | // The PutUint64()s are inlined and we get 4x (load, bswap, store) instructions. 164 | binary.BigEndian.PutUint64(dest[0:8], z[3]) 165 | binary.BigEndian.PutUint64(dest[8:16], z[2]) 166 | binary.BigEndian.PutUint64(dest[16:24], z[1]) 167 | binary.BigEndian.PutUint64(dest[24:32], z[0]) 168 | } 169 | 170 | // WriteToArray20 writes the last 20 bytes of z to the destination array, including zero-bytes 171 | func (z *Int) WriteToArray20(dest *[20]byte) { 172 | // The PutUint*()s are inlined and we get 3x (load, bswap, store) instructions. 173 | binary.BigEndian.PutUint32(dest[0:4], uint32(z[2])) 174 | binary.BigEndian.PutUint64(dest[4:12], z[1]) 175 | binary.BigEndian.PutUint64(dest[12:20], z[0]) 176 | } 177 | 178 | // Uint64 returns the lower 64-bits of z 179 | func (z *Int) Uint64() uint64 { 180 | return z[0] 181 | } 182 | 183 | // Uint64WithOverflow returns the lower 64-bits of z and bool whether overflow occurred 184 | func (z *Int) Uint64WithOverflow() (uint64, bool) { 185 | return z[0], (z[1] | z[2] | z[3]) != 0 186 | } 187 | 188 | // Clone creates a new Int identical to z 189 | func (z *Int) Clone() *Int { 190 | return &Int{z[0], z[1], z[2], z[3]} 191 | } 192 | 193 | // Add sets z to the sum x+y 194 | func (z *Int) Add(x, y *Int) *Int { 195 | var carry uint64 196 | z[0], carry = bits.Add64(x[0], y[0], 0) 197 | z[1], carry = bits.Add64(x[1], y[1], carry) 198 | z[2], carry = bits.Add64(x[2], y[2], carry) 199 | z[3], _ = bits.Add64(x[3], y[3], carry) 200 | return z 201 | } 202 | 203 | // AddOverflow sets z to the sum x+y, and returns z and whether overflow occurred 204 | func (z *Int) AddOverflow(x, y *Int) (*Int, bool) { 205 | var carry uint64 206 | z[0], carry = bits.Add64(x[0], y[0], 0) 207 | z[1], carry = bits.Add64(x[1], y[1], carry) 208 | z[2], carry = bits.Add64(x[2], y[2], carry) 209 | z[3], carry = bits.Add64(x[3], y[3], carry) 210 | return z, carry != 0 211 | } 212 | 213 | // AddMod sets z to the sum ( x+y ) mod m, and returns z. 214 | // If m == 0, z is set to 0 (OBS: differs from the big.Int) 215 | func (z *Int) AddMod(x, y, m *Int) *Int { 216 | 217 | // Fast path for m >= 2^192, with x and y at most slightly bigger than m. 218 | // This is always the case when x and y are already reduced modulo such m. 219 | 220 | if (m[3] != 0) && (x[3] <= m[3]) && (y[3] <= m[3]) { 221 | var ( 222 | gteC1 uint64 223 | gteC2 uint64 224 | tmpX Int 225 | tmpY Int 226 | res Int 227 | ) 228 | 229 | // reduce x/y modulo m if they are gte m 230 | tmpX[0], gteC1 = bits.Sub64(x[0], m[0], gteC1) 231 | tmpX[1], gteC1 = bits.Sub64(x[1], m[1], gteC1) 232 | tmpX[2], gteC1 = bits.Sub64(x[2], m[2], gteC1) 233 | tmpX[3], gteC1 = bits.Sub64(x[3], m[3], gteC1) 234 | 235 | tmpY[0], gteC2 = bits.Sub64(y[0], m[0], gteC2) 236 | tmpY[1], gteC2 = bits.Sub64(y[1], m[1], gteC2) 237 | tmpY[2], gteC2 = bits.Sub64(y[2], m[2], gteC2) 238 | tmpY[3], gteC2 = bits.Sub64(y[3], m[3], gteC2) 239 | 240 | if gteC1 == 0 { 241 | x = &tmpX 242 | } 243 | if gteC2 == 0 { 244 | y = &tmpY 245 | } 246 | var ( 247 | c1 uint64 248 | c2 uint64 249 | tmp Int 250 | ) 251 | 252 | res[0], c1 = bits.Add64(x[0], y[0], c1) 253 | res[1], c1 = bits.Add64(x[1], y[1], c1) 254 | res[2], c1 = bits.Add64(x[2], y[2], c1) 255 | res[3], c1 = bits.Add64(x[3], y[3], c1) 256 | 257 | tmp[0], c2 = bits.Sub64(res[0], m[0], c2) 258 | tmp[1], c2 = bits.Sub64(res[1], m[1], c2) 259 | tmp[2], c2 = bits.Sub64(res[2], m[2], c2) 260 | tmp[3], c2 = bits.Sub64(res[3], m[3], c2) 261 | 262 | // final sub was unnecessary 263 | if c1 == 0 && c2 != 0 { 264 | return z.Set(&res) 265 | } 266 | 267 | return z.Set(&tmp) 268 | } 269 | 270 | if m.IsZero() { 271 | return z.Clear() 272 | } 273 | if z == m { // z is an alias for m and will be overwritten by AddOverflow before m is read 274 | m = m.Clone() 275 | } 276 | if _, overflow := z.AddOverflow(x, y); overflow { 277 | sum := [5]uint64{z[0], z[1], z[2], z[3], 1} 278 | var quot [5]uint64 279 | var rem Int 280 | udivrem(quot[:], sum[:], m, &rem) 281 | return z.Set(&rem) 282 | } 283 | return z.Mod(z, m) 284 | } 285 | 286 | // AddUint64 sets z to x + y, where y is a uint64, and returns z 287 | func (z *Int) AddUint64(x *Int, y uint64) *Int { 288 | var carry uint64 289 | 290 | z[0], carry = bits.Add64(x[0], y, 0) 291 | z[1], carry = bits.Add64(x[1], 0, carry) 292 | z[2], carry = bits.Add64(x[2], 0, carry) 293 | z[3], _ = bits.Add64(x[3], 0, carry) 294 | return z 295 | } 296 | 297 | // PaddedBytes encodes a Int as a 0-padded byte slice. The length 298 | // of the slice is at least n bytes. 299 | // 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] 300 | func (z *Int) PaddedBytes(n int) []byte { 301 | b := make([]byte, n) 302 | 303 | for i := 0; i < 32 && i < n; i++ { 304 | b[n-1-i] = byte(z[i/8] >> uint64(8*(i%8))) 305 | } 306 | return b 307 | } 308 | 309 | // SubUint64 set z to the difference x - y, where y is a uint64, and returns z 310 | func (z *Int) SubUint64(x *Int, y uint64) *Int { 311 | var carry uint64 312 | z[0], carry = bits.Sub64(x[0], y, carry) 313 | z[1], carry = bits.Sub64(x[1], 0, carry) 314 | z[2], carry = bits.Sub64(x[2], 0, carry) 315 | z[3], _ = bits.Sub64(x[3], 0, carry) 316 | return z 317 | } 318 | 319 | // SubOverflow sets z to the difference x-y and returns z and true if the operation underflowed 320 | func (z *Int) SubOverflow(x, y *Int) (*Int, bool) { 321 | var carry uint64 322 | z[0], carry = bits.Sub64(x[0], y[0], 0) 323 | z[1], carry = bits.Sub64(x[1], y[1], carry) 324 | z[2], carry = bits.Sub64(x[2], y[2], carry) 325 | z[3], carry = bits.Sub64(x[3], y[3], carry) 326 | return z, carry != 0 327 | } 328 | 329 | // Sub sets z to the difference x-y 330 | func (z *Int) Sub(x, y *Int) *Int { 331 | var carry uint64 332 | z[0], carry = bits.Sub64(x[0], y[0], 0) 333 | z[1], carry = bits.Sub64(x[1], y[1], carry) 334 | z[2], carry = bits.Sub64(x[2], y[2], carry) 335 | z[3], _ = bits.Sub64(x[3], y[3], carry) 336 | return z 337 | } 338 | 339 | // umulStep computes (hi * 2^64 + lo) = z + (x * y) + carry. 340 | func umulStep(z, x, y, carry uint64) (hi, lo uint64) { 341 | hi, lo = bits.Mul64(x, y) 342 | lo, carry = bits.Add64(lo, carry, 0) 343 | hi, _ = bits.Add64(hi, 0, carry) 344 | lo, carry = bits.Add64(lo, z, 0) 345 | hi, _ = bits.Add64(hi, 0, carry) 346 | return hi, lo 347 | } 348 | 349 | // umulHop computes (hi * 2^64 + lo) = z + (x * y) 350 | func umulHop(z, x, y uint64) (hi, lo uint64) { 351 | hi, lo = bits.Mul64(x, y) 352 | lo, carry := bits.Add64(lo, z, 0) 353 | hi, _ = bits.Add64(hi, 0, carry) 354 | return hi, lo 355 | } 356 | 357 | // umul computes full 256 x 256 -> 512 multiplication. 358 | func umul(x, y *Int, res *[8]uint64) { 359 | var ( 360 | carry, carry4, carry5, carry6 uint64 361 | res1, res2, res3, res4, res5 uint64 362 | ) 363 | 364 | carry, res[0] = bits.Mul64(x[0], y[0]) 365 | carry, res1 = umulHop(carry, x[1], y[0]) 366 | carry, res2 = umulHop(carry, x[2], y[0]) 367 | carry4, res3 = umulHop(carry, x[3], y[0]) 368 | 369 | carry, res[1] = umulHop(res1, x[0], y[1]) 370 | carry, res2 = umulStep(res2, x[1], y[1], carry) 371 | carry, res3 = umulStep(res3, x[2], y[1], carry) 372 | carry5, res4 = umulStep(carry4, x[3], y[1], carry) 373 | 374 | carry, res[2] = umulHop(res2, x[0], y[2]) 375 | carry, res3 = umulStep(res3, x[1], y[2], carry) 376 | carry, res4 = umulStep(res4, x[2], y[2], carry) 377 | carry6, res5 = umulStep(carry5, x[3], y[2], carry) 378 | 379 | carry, res[3] = umulHop(res3, x[0], y[3]) 380 | carry, res[4] = umulStep(res4, x[1], y[3], carry) 381 | carry, res[5] = umulStep(res5, x[2], y[3], carry) 382 | res[7], res[6] = umulStep(carry6, x[3], y[3], carry) 383 | } 384 | 385 | // Mul sets z to the product x*y 386 | func (z *Int) Mul(x, y *Int) *Int { 387 | var ( 388 | carry0, carry1, carry2 uint64 389 | res1, res2 uint64 390 | x0, x1, x2, x3 = x[0], x[1], x[2], x[3] 391 | y0, y1, y2, y3 = y[0], y[1], y[2], y[3] 392 | ) 393 | 394 | carry0, z[0] = bits.Mul64(x0, y0) 395 | carry0, res1 = umulHop(carry0, x1, y0) 396 | carry0, res2 = umulHop(carry0, x2, y0) 397 | 398 | carry1, z[1] = umulHop(res1, x0, y1) 399 | carry1, res2 = umulStep(res2, x1, y1, carry1) 400 | 401 | carry2, z[2] = umulHop(res2, x0, y2) 402 | 403 | z[3] = x3*y0 + x2*y1 + x0*y3 + x1*y2 + carry0 + carry1 + carry2 404 | return z 405 | } 406 | 407 | // MulOverflow sets z to the product x*y, and returns z and whether overflow occurred 408 | func (z *Int) MulOverflow(x, y *Int) (*Int, bool) { 409 | var p [8]uint64 410 | umul(x, y, &p) 411 | copy(z[:], p[:4]) 412 | return z, (p[4] | p[5] | p[6] | p[7]) != 0 413 | } 414 | 415 | func (z *Int) squared() { 416 | var ( 417 | carry0, carry1, carry2 uint64 418 | res0, res1, res2, res3 uint64 419 | ) 420 | 421 | carry0, res0 = bits.Mul64(z[0], z[0]) 422 | carry0, res1 = umulHop(carry0, z[0], z[1]) 423 | carry0, res2 = umulHop(carry0, z[0], z[2]) 424 | 425 | carry1, res1 = umulHop(res1, z[0], z[1]) 426 | carry1, res2 = umulStep(res2, z[1], z[1], carry1) 427 | 428 | carry2, res2 = umulHop(res2, z[0], z[2]) 429 | 430 | res3 = 2*(z[0]*z[3]+z[1]*z[2]) + carry0 + carry1 + carry2 431 | 432 | z[0], z[1], z[2], z[3] = res0, res1, res2, res3 433 | } 434 | 435 | // isBitSet returns true if bit n-th is set, where n = 0 is LSB. 436 | // The n must be <= 255. 437 | func (z *Int) isBitSet(n uint) bool { 438 | return (z[n/64] & (1 << (n % 64))) != 0 439 | } 440 | 441 | // addTo computes x += y. 442 | // Requires len(x) >= len(y) > 0. 443 | func addTo(x, y []uint64) uint64 { 444 | var carry uint64 445 | _ = x[len(y)-1] // bounds check hint to compiler; see golang.org/issue/14808 446 | for i := 0; i < len(y); i++ { 447 | x[i], carry = bits.Add64(x[i], y[i], carry) 448 | } 449 | return carry 450 | } 451 | 452 | // subMulTo computes x -= y * multiplier. 453 | // Requires len(x) >= len(y) > 0. 454 | func subMulTo(x, y []uint64, multiplier uint64) uint64 { 455 | var borrow uint64 456 | _ = x[len(y)-1] // bounds check hint to compiler; see golang.org/issue/14808 457 | for i := 0; i < len(y); i++ { 458 | s, carry1 := bits.Sub64(x[i], borrow, 0) 459 | ph, pl := bits.Mul64(y[i], multiplier) 460 | t, carry2 := bits.Sub64(s, pl, 0) 461 | x[i] = t 462 | borrow = ph + carry1 + carry2 463 | } 464 | return borrow 465 | } 466 | 467 | // udivremBy1 divides u by single normalized word d and produces both quotient and remainder. 468 | // The quotient is stored in provided quot. 469 | func udivremBy1(quot, u []uint64, d uint64) (rem uint64) { 470 | reciprocal := reciprocal2by1(d) 471 | rem = u[len(u)-1] // Set the top word as remainder. 472 | for j := len(u) - 2; j >= 0; j-- { 473 | quot[j], rem = udivrem2by1(rem, u[j], d, reciprocal) 474 | } 475 | return rem 476 | } 477 | 478 | // udivremKnuth implements the division of u by normalized multiple word d from the Knuth's division algorithm. 479 | // The quotient is stored in provided quot - len(u)-len(d) words. 480 | // Updates u to contain the remainder - len(d) words. 481 | func udivremKnuth(quot, u, d []uint64) { 482 | dh := d[len(d)-1] 483 | dl := d[len(d)-2] 484 | reciprocal := reciprocal2by1(dh) 485 | 486 | for j := len(u) - len(d) - 1; j >= 0; j-- { 487 | u2 := u[j+len(d)] 488 | u1 := u[j+len(d)-1] 489 | u0 := u[j+len(d)-2] 490 | 491 | var qhat, rhat uint64 492 | if u2 >= dh { // Division overflows. 493 | qhat = ^uint64(0) 494 | // TODO: Add "qhat one to big" adjustment (not needed for correctness, but helps avoiding "add back" case). 495 | } else { 496 | qhat, rhat = udivrem2by1(u2, u1, dh, reciprocal) 497 | ph, pl := bits.Mul64(qhat, dl) 498 | if ph > rhat || (ph == rhat && pl > u0) { 499 | qhat-- 500 | // TODO: Add "qhat one to big" adjustment (not needed for correctness, but helps avoiding "add back" case). 501 | } 502 | } 503 | 504 | // Multiply and subtract. 505 | borrow := subMulTo(u[j:], d, qhat) 506 | u[j+len(d)] = u2 - borrow 507 | if u2 < borrow { // Too much subtracted, add back. 508 | qhat-- 509 | u[j+len(d)] += addTo(u[j:], d) 510 | } 511 | 512 | quot[j] = qhat // Store quotient digit. 513 | } 514 | } 515 | 516 | // udivrem divides u by d and produces both quotient and remainder. 517 | // The quotient is stored in provided quot - len(u)-len(d)+1 words. 518 | // It loosely follows the Knuth's division algorithm (sometimes referenced as "schoolbook" division) using 64-bit words. 519 | // See Knuth, Volume 2, section 4.3.1, Algorithm D. 520 | func udivrem(quot, u []uint64, d, rem *Int) { 521 | var dLen int 522 | for i := len(d) - 1; i >= 0; i-- { 523 | if d[i] != 0 { 524 | dLen = i + 1 525 | break 526 | } 527 | } 528 | 529 | shift := uint(bits.LeadingZeros64(d[dLen-1])) 530 | 531 | var dnStorage Int 532 | dn := dnStorage[:dLen] 533 | for i := dLen - 1; i > 0; i-- { 534 | dn[i] = (d[i] << shift) | (d[i-1] >> (64 - shift)) 535 | } 536 | dn[0] = d[0] << shift 537 | 538 | var uLen int 539 | for i := len(u) - 1; i >= 0; i-- { 540 | if u[i] != 0 { 541 | uLen = i + 1 542 | break 543 | } 544 | } 545 | 546 | if uLen < dLen { 547 | if rem != nil { 548 | copy(rem[:], u) 549 | } 550 | return 551 | } 552 | 553 | var unStorage [9]uint64 554 | un := unStorage[:uLen+1] 555 | un[uLen] = u[uLen-1] >> (64 - shift) 556 | for i := uLen - 1; i > 0; i-- { 557 | un[i] = (u[i] << shift) | (u[i-1] >> (64 - shift)) 558 | } 559 | un[0] = u[0] << shift 560 | 561 | // TODO: Skip the highest word of numerator if not significant. 562 | 563 | if dLen == 1 { 564 | r := udivremBy1(quot, un, dn[0]) 565 | if rem != nil { 566 | rem.SetUint64(r >> shift) 567 | } 568 | return 569 | } 570 | 571 | udivremKnuth(quot, un, dn) 572 | 573 | if rem != nil { 574 | for i := 0; i < dLen-1; i++ { 575 | rem[i] = (un[i] >> shift) | (un[i+1] << (64 - shift)) 576 | } 577 | rem[dLen-1] = un[dLen-1] >> shift 578 | } 579 | } 580 | 581 | // Div sets z to the quotient x/y for returns z. 582 | // If y == 0, z is set to 0 583 | func (z *Int) Div(x, y *Int) *Int { 584 | if y.IsZero() || y.Gt(x) { 585 | return z.Clear() 586 | } 587 | if x.Eq(y) { 588 | return z.SetOne() 589 | } 590 | // Shortcut some cases 591 | if x.IsUint64() { 592 | return z.SetUint64(x.Uint64() / y.Uint64()) 593 | } 594 | 595 | // At this point, we know 596 | // x/y ; x > y > 0 597 | 598 | var quot Int 599 | udivrem(quot[:], x[:], y, nil) 600 | return z.Set(") 601 | } 602 | 603 | // Mod sets z to the modulus x%y for y != 0 and returns z. 604 | // If y == 0, z is set to 0 (OBS: differs from the big.Int) 605 | func (z *Int) Mod(x, y *Int) *Int { 606 | if y.IsZero() || x.Eq(y) { 607 | return z.Clear() 608 | } 609 | if x.Lt(y) { 610 | return z.Set(x) 611 | } 612 | // At this point: 613 | // x != 0 614 | // y != 0 615 | // x > y 616 | 617 | // Shortcut trivial case 618 | if x.IsUint64() { 619 | return z.SetUint64(x.Uint64() % y.Uint64()) 620 | } 621 | 622 | var quot, rem Int 623 | udivrem(quot[:], x[:], y, &rem) 624 | return z.Set(&rem) 625 | } 626 | 627 | // 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. 628 | // If y == 0, both z and m are set to 0 (OBS: differs from the big.Int) 629 | func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) { 630 | if z == m { 631 | // We return both z and m as results, if they are aliased, we have to 632 | // un-alias them to be able to return separate results. 633 | m = new(Int).Set(m) 634 | } 635 | if y.IsZero() { 636 | return z.Clear(), m.Clear() 637 | } 638 | if x.Eq(y) { 639 | return z.SetOne(), m.Clear() 640 | } 641 | if x.Lt(y) { 642 | m.Set(x) 643 | return z.Clear(), m 644 | } 645 | 646 | // At this point: 647 | // x != 0 648 | // y != 0 649 | // x > y 650 | 651 | // Shortcut trivial case 652 | if x.IsUint64() { 653 | x0, y0 := x.Uint64(), y.Uint64() 654 | return z.SetUint64(x0 / y0), m.SetUint64(x0 % y0) 655 | } 656 | 657 | var quot, rem Int 658 | udivrem(quot[:], x[:], y, &rem) 659 | return z.Set("), m.Set(&rem) 660 | } 661 | 662 | // SMod interprets x and y as two's complement signed integers, 663 | // sets z to (sign x) * { abs(x) modulus abs(y) } 664 | // If y == 0, z is set to 0 (OBS: differs from the big.Int) 665 | func (z *Int) SMod(x, y *Int) *Int { 666 | ys := y.Sign() 667 | xs := x.Sign() 668 | 669 | // abs x 670 | if xs == -1 { 671 | x = new(Int).Neg(x) 672 | } 673 | // abs y 674 | if ys == -1 { 675 | y = new(Int).Neg(y) 676 | } 677 | z.Mod(x, y) 678 | if xs == -1 { 679 | z.Neg(z) 680 | } 681 | return z 682 | } 683 | 684 | // MulModWithReciprocal calculates the modulo-m multiplication of x and y 685 | // and returns z, using the reciprocal of m provided as the mu parameter. 686 | // Use uint256.Reciprocal to calculate mu from m. 687 | // If m == 0, z is set to 0 (OBS: differs from the big.Int) 688 | func (z *Int) MulModWithReciprocal(x, y, m *Int, mu *[5]uint64) *Int { 689 | if x.IsZero() || y.IsZero() || m.IsZero() { 690 | return z.Clear() 691 | } 692 | var p [8]uint64 693 | umul(x, y, &p) 694 | 695 | if m[3] != 0 { 696 | return z.reduce4(&p, m, mu) 697 | } 698 | 699 | var ( 700 | pl Int 701 | ph Int 702 | ) 703 | pl[0], pl[1], pl[2], pl[3] = p[0], p[1], p[2], p[3] 704 | ph[0], ph[1], ph[2], ph[3] = p[4], p[5], p[6], p[7] 705 | 706 | // If the multiplication is within 256 bits use Mod(). 707 | if ph.IsZero() { 708 | return z.Mod(&pl, m) 709 | } 710 | 711 | var quot [8]uint64 712 | var rem Int 713 | udivrem(quot[:], p[:], m, &rem) 714 | return z.Set(&rem) 715 | } 716 | 717 | // MulMod calculates the modulo-m multiplication of x and y and 718 | // returns z. 719 | // If m == 0, z is set to 0 (OBS: differs from the big.Int) 720 | func (z *Int) MulMod(x, y, m *Int) *Int { 721 | if x.IsZero() || y.IsZero() || m.IsZero() { 722 | return z.Clear() 723 | } 724 | var p [8]uint64 725 | umul(x, y, &p) 726 | 727 | if m[3] != 0 { 728 | mu := Reciprocal(m) 729 | return z.reduce4(&p, m, &mu) 730 | } 731 | 732 | var ( 733 | pl Int 734 | ph Int 735 | ) 736 | pl[0], pl[1], pl[2], pl[3] = p[0], p[1], p[2], p[3] 737 | ph[0], ph[1], ph[2], ph[3] = p[4], p[5], p[6], p[7] 738 | 739 | // If the multiplication is within 256 bits use Mod(). 740 | if ph.IsZero() { 741 | return z.Mod(&pl, m) 742 | } 743 | 744 | var quot [8]uint64 745 | var rem Int 746 | udivrem(quot[:], p[:], m, &rem) 747 | return z.Set(&rem) 748 | } 749 | 750 | // MulDivOverflow calculates (x*y)/d with full precision, returns z and whether overflow occurred in multiply process (result does not fit to 256-bit). 751 | // computes 512-bit multiplication and 512 by 256 division. 752 | func (z *Int) MulDivOverflow(x, y, d *Int) (*Int, bool) { 753 | if x.IsZero() || y.IsZero() || d.IsZero() { 754 | return z.Clear(), false 755 | } 756 | var p [8]uint64 757 | umul(x, y, &p) 758 | 759 | var quot [8]uint64 760 | udivrem(quot[:], p[:], d, nil) 761 | 762 | z[0], z[1], z[2], z[3] = quot[0], quot[1], quot[2], quot[3] 763 | 764 | return z, (quot[4] | quot[5] | quot[6] | quot[7]) != 0 765 | } 766 | 767 | // Abs interprets x as a two's complement signed number, 768 | // and sets z to the absolute value 769 | // 770 | // Abs(0) = 0 771 | // Abs(1) = 1 772 | // Abs(2**255) = -2**255 773 | // Abs(2**256-1) = -1 774 | func (z *Int) Abs(x *Int) *Int { 775 | if x[3] < 0x8000000000000000 { 776 | return z.Set(x) 777 | } 778 | return z.Sub(new(Int), x) 779 | } 780 | 781 | // Neg returns -x mod 2**256. 782 | func (z *Int) Neg(x *Int) *Int { 783 | return z.Sub(new(Int), x) 784 | } 785 | 786 | // SDiv interprets n and d as two's complement signed integers, 787 | // does a signed division on the two operands and sets z to the result. 788 | // If d == 0, z is set to 0 789 | func (z *Int) SDiv(n, d *Int) *Int { 790 | if n.Sign() > 0 { 791 | if d.Sign() > 0 { 792 | // pos / pos 793 | z.Div(n, d) 794 | return z 795 | } else { 796 | // pos / neg 797 | z.Div(n, new(Int).Neg(d)) 798 | return z.Neg(z) 799 | } 800 | } 801 | 802 | if d.Sign() < 0 { 803 | // neg / neg 804 | z.Div(new(Int).Neg(n), new(Int).Neg(d)) 805 | return z 806 | } 807 | // neg / pos 808 | z.Div(new(Int).Neg(n), d) 809 | return z.Neg(z) 810 | } 811 | 812 | // Sign returns: 813 | // 814 | // -1 if z < 0 815 | // 0 if z == 0 816 | // +1 if z > 0 817 | // 818 | // Where z is interpreted as a two's complement signed number 819 | func (z *Int) Sign() int { 820 | if z.IsZero() { 821 | return 0 822 | } 823 | if z[3] < 0x8000000000000000 { 824 | return 1 825 | } 826 | return -1 827 | } 828 | 829 | // BitLen returns the number of bits required to represent z 830 | func (z *Int) BitLen() int { 831 | switch { 832 | case z[3] != 0: 833 | return 192 + bits.Len64(z[3]) 834 | case z[2] != 0: 835 | return 128 + bits.Len64(z[2]) 836 | case z[1] != 0: 837 | return 64 + bits.Len64(z[1]) 838 | default: 839 | return bits.Len64(z[0]) 840 | } 841 | } 842 | 843 | // ByteLen returns the number of bytes required to represent z 844 | func (z *Int) ByteLen() int { 845 | return (z.BitLen() + 7) / 8 846 | } 847 | 848 | func (z *Int) lsh64(x *Int) { 849 | z[3], z[2], z[1], z[0] = x[2], x[1], x[0], 0 850 | } 851 | 852 | func (z *Int) lsh128(x *Int) { 853 | z[3], z[2], z[1], z[0] = x[1], x[0], 0, 0 854 | } 855 | 856 | func (z *Int) lsh192(x *Int) { 857 | z[3], z[2], z[1], z[0] = x[0], 0, 0, 0 858 | } 859 | 860 | func (z *Int) rsh64(x *Int) { 861 | z[3], z[2], z[1], z[0] = 0, x[3], x[2], x[1] 862 | } 863 | 864 | func (z *Int) rsh128(x *Int) { 865 | z[3], z[2], z[1], z[0] = 0, 0, x[3], x[2] 866 | } 867 | 868 | func (z *Int) rsh192(x *Int) { 869 | z[3], z[2], z[1], z[0] = 0, 0, 0, x[3] 870 | } 871 | 872 | func (z *Int) srsh64(x *Int) { 873 | z[3], z[2], z[1], z[0] = math.MaxUint64, x[3], x[2], x[1] 874 | } 875 | 876 | func (z *Int) srsh128(x *Int) { 877 | z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, x[3], x[2] 878 | } 879 | 880 | func (z *Int) srsh192(x *Int) { 881 | z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, math.MaxUint64, x[3] 882 | } 883 | 884 | // Not sets z = ^x and returns z. 885 | func (z *Int) Not(x *Int) *Int { 886 | z[3], z[2], z[1], z[0] = ^x[3], ^x[2], ^x[1], ^x[0] 887 | return z 888 | } 889 | 890 | // Gt returns true if z > x 891 | func (z *Int) Gt(x *Int) bool { 892 | return x.Lt(z) 893 | } 894 | 895 | // Slt interprets z and x as signed integers, and returns 896 | // true if z < x 897 | func (z *Int) Slt(x *Int) bool { 898 | 899 | zSign := z.Sign() 900 | xSign := x.Sign() 901 | 902 | switch { 903 | case zSign >= 0 && xSign < 0: 904 | return false 905 | case zSign < 0 && xSign >= 0: 906 | return true 907 | default: 908 | return z.Lt(x) 909 | } 910 | } 911 | 912 | // Sgt interprets z and x as signed integers, and returns 913 | // true if z > x 914 | func (z *Int) Sgt(x *Int) bool { 915 | zSign := z.Sign() 916 | xSign := x.Sign() 917 | 918 | switch { 919 | case zSign >= 0 && xSign < 0: 920 | return true 921 | case zSign < 0 && xSign >= 0: 922 | return false 923 | default: 924 | return z.Gt(x) 925 | } 926 | } 927 | 928 | // Lt returns true if z < x 929 | func (z *Int) Lt(x *Int) bool { 930 | // z < x <=> z - x < 0 i.e. when subtraction overflows. 931 | _, carry := bits.Sub64(z[0], x[0], 0) 932 | _, carry = bits.Sub64(z[1], x[1], carry) 933 | _, carry = bits.Sub64(z[2], x[2], carry) 934 | _, carry = bits.Sub64(z[3], x[3], carry) 935 | return carry != 0 936 | } 937 | 938 | // SetUint64 sets z to the value x 939 | func (z *Int) SetUint64(x uint64) *Int { 940 | z[3], z[2], z[1], z[0] = 0, 0, 0, x 941 | return z 942 | } 943 | 944 | // Eq returns true if z == x 945 | func (z *Int) Eq(x *Int) bool { 946 | return (z[0] == x[0]) && (z[1] == x[1]) && (z[2] == x[2]) && (z[3] == x[3]) 947 | } 948 | 949 | // Cmp compares z and x and returns: 950 | // 951 | // -1 if z < x 952 | // 0 if z == x 953 | // +1 if z > x 954 | func (z *Int) Cmp(x *Int) (r int) { 955 | // z < x <=> z - x < 0 i.e. when subtraction overflows. 956 | d0, carry := bits.Sub64(z[0], x[0], 0) 957 | d1, carry := bits.Sub64(z[1], x[1], carry) 958 | d2, carry := bits.Sub64(z[2], x[2], carry) 959 | d3, carry := bits.Sub64(z[3], x[3], carry) 960 | if carry == 1 { 961 | return -1 962 | } 963 | if d0|d1|d2|d3 == 0 { 964 | return 0 965 | } 966 | return 1 967 | } 968 | 969 | // CmpUint64 compares z and x and returns: 970 | // 971 | // -1 if z < x 972 | // 0 if z == x 973 | // +1 if z > x 974 | func (z *Int) CmpUint64(x uint64) int { 975 | if z[0] > x || (z[1]|z[2]|z[3]) != 0 { 976 | return 1 977 | } 978 | if z[0] == x { 979 | return 0 980 | } 981 | return -1 982 | } 983 | 984 | // CmpBig compares z and x and returns: 985 | // 986 | // -1 if z < x 987 | // 0 if z == x 988 | // +1 if z > x 989 | func (z *Int) CmpBig(x *big.Int) (r int) { 990 | // If x is negative, it's surely smaller (z > x) 991 | if x.Sign() == -1 { 992 | return 1 993 | } 994 | y := new(Int) 995 | if y.SetFromBig(x) { // overflow 996 | // z < x 997 | return -1 998 | } 999 | return z.Cmp(y) 1000 | } 1001 | 1002 | // LtUint64 returns true if z is smaller than n 1003 | func (z *Int) LtUint64(n uint64) bool { 1004 | return z[0] < n && (z[1]|z[2]|z[3]) == 0 1005 | } 1006 | 1007 | // GtUint64 returns true if z is larger than n 1008 | func (z *Int) GtUint64(n uint64) bool { 1009 | return z[0] > n || (z[1]|z[2]|z[3]) != 0 1010 | } 1011 | 1012 | // IsUint64 reports whether z can be represented as a uint64. 1013 | func (z *Int) IsUint64() bool { 1014 | return (z[1] | z[2] | z[3]) == 0 1015 | } 1016 | 1017 | // IsZero returns true if z == 0 1018 | func (z *Int) IsZero() bool { 1019 | return (z[0] | z[1] | z[2] | z[3]) == 0 1020 | } 1021 | 1022 | // Clear sets z to 0 1023 | func (z *Int) Clear() *Int { 1024 | z[3], z[2], z[1], z[0] = 0, 0, 0, 0 1025 | return z 1026 | } 1027 | 1028 | // SetAllOne sets all the bits of z to 1 1029 | func (z *Int) SetAllOne() *Int { 1030 | z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, math.MaxUint64, math.MaxUint64 1031 | return z 1032 | } 1033 | 1034 | // SetOne sets z to 1 1035 | func (z *Int) SetOne() *Int { 1036 | z[3], z[2], z[1], z[0] = 0, 0, 0, 1 1037 | return z 1038 | } 1039 | 1040 | // Lsh sets z = x << n and returns z. 1041 | func (z *Int) Lsh(x *Int, n uint) *Int { 1042 | switch { 1043 | case n == 0: 1044 | return z.Set(x) 1045 | case n >= 192: 1046 | z.lsh192(x) 1047 | n -= 192 1048 | z[3] <<= n 1049 | return z 1050 | case n >= 128: 1051 | z.lsh128(x) 1052 | n -= 128 1053 | z[3] = (z[3] << n) | (z[2] >> (64 - n)) 1054 | z[2] <<= n 1055 | return z 1056 | case n >= 64: 1057 | z.lsh64(x) 1058 | n -= 64 1059 | z[3] = (z[3] << n) | (z[2] >> (64 - n)) 1060 | z[2] = (z[2] << n) | (z[1] >> (64 - n)) 1061 | z[1] <<= n 1062 | return z 1063 | default: 1064 | z.Set(x) 1065 | z[3] = (z[3] << n) | (z[2] >> (64 - n)) 1066 | z[2] = (z[2] << n) | (z[1] >> (64 - n)) 1067 | z[1] = (z[1] << n) | (z[0] >> (64 - n)) 1068 | z[0] <<= n 1069 | return z 1070 | } 1071 | } 1072 | 1073 | // Rsh sets z = x >> n and returns z. 1074 | func (z *Int) Rsh(x *Int, n uint) *Int { 1075 | switch { 1076 | case n == 0: 1077 | return z.Set(x) 1078 | case n >= 192: 1079 | z.rsh192(x) 1080 | n -= 192 1081 | z[0] >>= n 1082 | return z 1083 | case n >= 128: 1084 | z.rsh128(x) 1085 | n -= 128 1086 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1087 | z[1] >>= n 1088 | return z 1089 | case n >= 64: 1090 | z.rsh64(x) 1091 | n -= 64 1092 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1093 | z[1] = (z[1] >> n) | (z[2] << (64 - n)) 1094 | z[2] >>= n 1095 | return z 1096 | default: 1097 | z.Set(x) 1098 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1099 | z[1] = (z[1] >> n) | (z[2] << (64 - n)) 1100 | z[2] = (z[2] >> n) | (z[3] << (64 - n)) 1101 | z[3] >>= n 1102 | return z 1103 | } 1104 | } 1105 | 1106 | // SRsh (Signed/Arithmetic right shift) 1107 | // considers z to be a signed integer, during right-shift 1108 | // and sets z = x >> n and returns z. 1109 | func (z *Int) SRsh(x *Int, n uint) *Int { 1110 | // If the MSB is 0, SRsh is same as Rsh. 1111 | if !x.isBitSet(255) { 1112 | return z.Rsh(x, n) 1113 | } 1114 | var a uint64 = math.MaxUint64 << (64 - n%64) 1115 | 1116 | switch { 1117 | case n == 0: 1118 | return z.Set(x) 1119 | case n >= 256: 1120 | return z.SetAllOne() 1121 | case n >= 192: 1122 | z.srsh192(x) 1123 | n -= 192 1124 | z[0] = (z[0] >> n) | a 1125 | return z 1126 | case n >= 128: 1127 | z.srsh128(x) 1128 | n -= 128 1129 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1130 | z[1] = (z[1] >> n) | a 1131 | return z 1132 | case n >= 64: 1133 | z.srsh64(x) 1134 | n -= 64 1135 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1136 | z[1] = (z[1] >> n) | (z[2] << (64 - n)) 1137 | z[2] = (z[2] >> n) | a 1138 | return z 1139 | default: 1140 | z.Set(x) 1141 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1142 | z[1] = (z[1] >> n) | (z[2] << (64 - n)) 1143 | z[2] = (z[2] >> n) | (z[3] << (64 - n)) 1144 | z[3] = (z[3] >> n) | a 1145 | return z 1146 | } 1147 | } 1148 | 1149 | // Set sets z to x and returns z. 1150 | func (z *Int) Set(x *Int) *Int { 1151 | z[0], z[1], z[2], z[3] = x[0], x[1], x[2], x[3] 1152 | return z 1153 | } 1154 | 1155 | // Or sets z = x | y and returns z. 1156 | func (z *Int) Or(x, y *Int) *Int { 1157 | z[0] = x[0] | y[0] 1158 | z[1] = x[1] | y[1] 1159 | z[2] = x[2] | y[2] 1160 | z[3] = x[3] | y[3] 1161 | return z 1162 | } 1163 | 1164 | // And sets z = x & y and returns z. 1165 | func (z *Int) And(x, y *Int) *Int { 1166 | z[0] = x[0] & y[0] 1167 | z[1] = x[1] & y[1] 1168 | z[2] = x[2] & y[2] 1169 | z[3] = x[3] & y[3] 1170 | return z 1171 | } 1172 | 1173 | // Xor sets z = x ^ y and returns z. 1174 | func (z *Int) Xor(x, y *Int) *Int { 1175 | z[0] = x[0] ^ y[0] 1176 | z[1] = x[1] ^ y[1] 1177 | z[2] = x[2] ^ y[2] 1178 | z[3] = x[3] ^ y[3] 1179 | return z 1180 | } 1181 | 1182 | // Byte sets z to the value of the byte at position n, 1183 | // with z considered as a big-endian 32-byte integer. 1184 | // if n >= 32, z is set to 0 1185 | // Example: z=5, n=31 => 5 1186 | func (z *Int) Byte(n *Int) *Int { 1187 | index, overflow := n.Uint64WithOverflow() 1188 | if overflow || index >= 32 { 1189 | return z.Clear() 1190 | } 1191 | // in z, z[0] is the least significant 1192 | number := z[4-1-index/8] 1193 | offset := (index & 0x7) << 3 // 8 * (index % 8) 1194 | z[0] = (number >> (56 - offset)) & 0xff 1195 | z[3], z[2], z[1] = 0, 0, 0 1196 | return z 1197 | } 1198 | 1199 | // Exp sets z = base**exponent mod 2**256, and returns z. 1200 | func (z *Int) Exp(base, exponent *Int) *Int { 1201 | var ( 1202 | res = Int{1, 0, 0, 0} 1203 | multiplier = *base 1204 | expBitLen = exponent.BitLen() 1205 | curBit = 0 1206 | word = exponent[0] 1207 | even = base[0]&1 == 0 1208 | ) 1209 | if even && expBitLen > 8 { 1210 | return z.Clear() 1211 | } 1212 | 1213 | for ; curBit < expBitLen && curBit < 64; curBit++ { 1214 | if word&1 == 1 { 1215 | res.Mul(&res, &multiplier) 1216 | } 1217 | multiplier.squared() 1218 | word >>= 1 1219 | } 1220 | if even { // If the base was even, we are finished now 1221 | return z.Set(&res) 1222 | } 1223 | 1224 | word = exponent[1] 1225 | for ; curBit < expBitLen && curBit < 128; curBit++ { 1226 | if word&1 == 1 { 1227 | res.Mul(&res, &multiplier) 1228 | } 1229 | multiplier.squared() 1230 | word >>= 1 1231 | } 1232 | 1233 | word = exponent[2] 1234 | for ; curBit < expBitLen && curBit < 192; curBit++ { 1235 | if word&1 == 1 { 1236 | res.Mul(&res, &multiplier) 1237 | } 1238 | multiplier.squared() 1239 | word >>= 1 1240 | } 1241 | 1242 | word = exponent[3] 1243 | for ; curBit < expBitLen && curBit < 256; curBit++ { 1244 | if word&1 == 1 { 1245 | res.Mul(&res, &multiplier) 1246 | } 1247 | multiplier.squared() 1248 | word >>= 1 1249 | } 1250 | return z.Set(&res) 1251 | } 1252 | 1253 | // ExtendSign extends length of two’s complement signed integer, 1254 | // sets z to 1255 | // - x if byteNum > 30 1256 | // - x interpreted as a signed number with sign-bit at (byteNum*8+7), extended to the full 256 bits 1257 | // 1258 | // and returns z. 1259 | func (z *Int) ExtendSign(x, byteNum *Int) *Int { 1260 | // This implementation is based on evmone. See https://github.com/ethereum/evmone/pull/390 1261 | if byteNum.GtUint64(30) { 1262 | return z.Set(x) 1263 | } 1264 | 1265 | e := byteNum.Uint64() 1266 | z.Set(x) 1267 | signWordIndex := e >> 3 // Index of the word with the sign bit. 1268 | signByteIndex := e & 7 // Index of the sign byte in the sign word. 1269 | signWord := z[signWordIndex] 1270 | signByteOffset := signByteIndex << 3 1271 | signByte := signWord >> signByteOffset // Move sign byte to position 0. 1272 | 1273 | // Sign-extend the "sign" byte and move it to the right position. Value bits are zeros. 1274 | sextByte := uint64(int64(int8(signByte))) 1275 | sext := sextByte << signByteOffset 1276 | signMask := uint64(math.MaxUint64 << signByteOffset) 1277 | value := signWord & ^signMask // Reset extended bytes. 1278 | 1279 | z[signWordIndex] = sext | value // Combine the result word. 1280 | 1281 | // Produce bits (all zeros or ones) for extended words. This is done by SAR of 1282 | // the sign-extended byte. Shift by any value 7-63 would work. 1283 | signEx := uint64(int64(sextByte) >> 8) 1284 | 1285 | switch signWordIndex { 1286 | case 2: 1287 | z[3] = signEx 1288 | return z 1289 | case 1: 1290 | z[3], z[2] = signEx, signEx 1291 | return z 1292 | case 0: 1293 | z[3], z[2], z[1] = signEx, signEx, signEx 1294 | return z 1295 | default: 1296 | return z 1297 | } 1298 | } 1299 | 1300 | // Sqrt sets z to ⌊√x⌋, the largest integer such that z² ≤ x, and returns z. 1301 | func (z *Int) Sqrt(x *Int) *Int { 1302 | // This implementation of Sqrt is based on big.Int (see math/big/nat.go). 1303 | if x.IsUint64() { 1304 | var ( 1305 | x0 uint64 = x.Uint64() 1306 | z1 uint64 = 1 << ((bits.Len64(x0) + 1) / 2) 1307 | z2 uint64 1308 | ) 1309 | if x0 < 2 { 1310 | return z.SetUint64(x0) 1311 | } 1312 | for { 1313 | z2 = (z1 + x0/z1) >> 1 1314 | if z2 >= z1 { 1315 | return z.SetUint64(z1) 1316 | } 1317 | z1 = z2 1318 | } 1319 | } 1320 | 1321 | z1 := NewInt(1) 1322 | z2 := NewInt(0) 1323 | 1324 | // Start with value known to be too large and repeat "z = ⌊(z + ⌊x/z⌋)/2⌋" until it stops getting smaller. 1325 | z1.Lsh(z1, uint(x.BitLen()+1)/2) // must be ≥ √x 1326 | 1327 | // We can do the first division outside the loop 1328 | z2.Rsh(x, uint(x.BitLen()+1)/2) // The first div is equal to a right shift 1329 | 1330 | for { 1331 | z2.Add(z2, z1) 1332 | 1333 | // z2 = z2.Rsh(z2, 1) -- the code below does a 1-bit rsh faster 1334 | z2[0] = (z2[0] >> 1) | z2[1]<<63 1335 | z2[1] = (z2[1] >> 1) | z2[2]<<63 1336 | z2[2] = (z2[2] >> 1) | z2[3]<<63 1337 | z2[3] >>= 1 1338 | 1339 | if !z2.Lt(z1) { 1340 | return z.Set(z1) 1341 | } 1342 | z1.Set(z2) 1343 | 1344 | // Next iteration of the loop 1345 | // z2.Div(x, z1) -- x > MaxUint64, x > z1 > 0 1346 | z2.Clear() 1347 | udivrem(z2[:], x[:], z1, nil) 1348 | } 1349 | } 1350 | 1351 | var ( 1352 | // pows64 contains 10^0 ... 10^19 1353 | pows64 = [20]uint64{ 1354 | 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1355 | } 1356 | // pows contain 10 ** 20 ... 10 ** 80 1357 | pows = [60]Int{ 1358 | {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}, 1359 | {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}, 1360 | {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}, 1361 | {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}, 1362 | {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}, 1363 | } 1364 | ) 1365 | 1366 | // Log10 returns the log in base 10, floored to nearest integer. 1367 | // **OBS** This method returns '0' for '0', not `-Inf`. 1368 | func (z *Int) Log10() uint { 1369 | // The following algorithm is taken from "Bit twiddling hacks" 1370 | // https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 1371 | // 1372 | // The idea is that log10(z) = log2(z) / log2(10) 1373 | // log2(z) trivially is z.Bitlen() 1374 | // 1/log2(10) is a constant ~ 1233 / 4096. The approximation is correct up to 5 digit after 1375 | // the decimal point and it seems no further refinement is needed. 1376 | // Our tests check all boundary cases anyway. 1377 | 1378 | bitlen := z.BitLen() 1379 | if bitlen == 0 { 1380 | return 0 1381 | } 1382 | 1383 | t := (bitlen + 1) * 1233 >> 12 1384 | if bitlen <= 64 && z[0] < pows64[t] || t >= 20 && z.Lt(&pows[t-20]) { 1385 | return uint(t - 1) 1386 | } 1387 | return uint(t) 1388 | } 1389 | -------------------------------------------------------------------------------- /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 TestRandomMulMod(t *testing.T) { 122 | for i := 0; i < 10000; i++ { 123 | b1, f1 := randNums() 124 | b2, f2 := randNums() 125 | b3, f3 := randNums() 126 | b4, f4 := randNums() 127 | for b4.Cmp(big.NewInt(0)) == 0 { 128 | b4, f4 = randNums() 129 | } 130 | 131 | f1.MulMod(f2, f3, f4) 132 | b1.Mod(big.NewInt(0).Mul(b2, b3), b4) 133 | 134 | if !checkEq(b1, f1) { 135 | t.Fatalf("Expected equality:\nf2= %x\nf3= %x\nf4= %x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f4, f1, b1) 136 | } 137 | 138 | f1.mulModWithReciprocalWrapper(f2, f3, f4) 139 | 140 | if !checkEq(b1, f1) { 141 | t.Fatalf("Expected equality:\nf2= %x\nf3= %x\nf4= %x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f4, f1, b1) 142 | } 143 | } 144 | 145 | // Tests related to powers of 2 146 | 147 | f_minusone := &Int{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} 148 | 149 | b_one := big.NewInt(1) 150 | b_minusone := big.NewInt(0) 151 | b_minusone = b_minusone.Sub(b_minusone, b_one) 152 | 153 | for i := uint(0); i < 256; i++ { 154 | b := big.NewInt(0) 155 | f := NewInt(0) 156 | 157 | t1, t2, t3 := b, b, b 158 | u1, u2, u3 := f, f, f 159 | 160 | b1 := b.Lsh(b, i) 161 | f1 := f.Lsh(f, i) 162 | 163 | b2, f2 := randNums() 164 | for b2.Cmp(big.NewInt(0)) == 0 { 165 | b2, f2 = randNums() 166 | } 167 | 168 | b3, f3 := randNums() 169 | for b3.Cmp(big.NewInt(0)) == 0 { 170 | b3, f3 = randNums() 171 | } 172 | 173 | // Tests with one operand a power of 2 174 | 175 | set3Big(b1, b2, b3, t1, t2, t3) 176 | set3Int(f1, f2, f3, u1, u2, u3) 177 | 178 | b.Mod(b.Mul(t1, t2), t3) 179 | f.MulMod(u1, u2, u3) 180 | 181 | if !checkEq(b, f) { 182 | t.Fatalf("Expected equality:\nf1= 0x%x\nf2= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f2, f3, f, b) 183 | } 184 | 185 | set3Big(b1, b2, b3, t1, t2, t3) 186 | set3Int(f1, f2, f3, u1, u2, u3) 187 | 188 | b.Mod(b.Mul(t1, t3), t2) 189 | f.MulMod(u1, u3, u2) 190 | 191 | if !checkEq(b, f) { 192 | t.Fatalf("Expected equality:\nf1= 0x%x\nf3= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f3, f2, f, b) 193 | } 194 | 195 | set3Big(b1, b2, b3, t1, t2, t3) 196 | set3Int(f1, f2, f3, u1, u2, u3) 197 | 198 | b.Mod(b.Mul(t2, t1), t3) 199 | f.MulMod(u2, u1, u3) 200 | 201 | if !checkEq(b, f) { 202 | t.Fatalf("Expected equality:\nf2= 0x%x\nf1= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f1, f3, f, b) 203 | } 204 | 205 | set3Big(b1, b2, b3, t1, t2, t3) 206 | set3Int(f1, f2, f3, u1, u2, u3) 207 | 208 | b.Mod(b.Mul(t2, t3), t1) 209 | f.MulMod(u2, u3, u1) 210 | 211 | if !checkEq(b, f) { 212 | t.Fatalf("Expected equality:\nf2= 0x%x\nf3= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f1, f, b) 213 | } 214 | 215 | set3Big(b1, b2, b3, t1, t2, t3) 216 | set3Int(f1, f2, f3, u1, u2, u3) 217 | 218 | b.Mod(b.Mul(t3, t1), t2) 219 | f.MulMod(u3, u1, u2) 220 | 221 | if !checkEq(b, f) { 222 | t.Fatalf("Expected equality:\nf3= 0x%x\nf1= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f1, f2, f, b) 223 | } 224 | 225 | set3Big(b1, b2, b3, t1, t2, t3) 226 | set3Int(f1, f2, f3, u1, u2, u3) 227 | 228 | b.Mod(b.Mul(t3, t2), t1) 229 | f.MulMod(u3, u2, u1) 230 | 231 | if !checkEq(b, f) { 232 | t.Fatalf("Expected equality:\nf3= 0x%x\nf2= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f2, f1, f, b) 233 | } 234 | 235 | // Tests with one operand 2^256 minus a power of 2 236 | 237 | f1.Xor(f1, f_minusone) 238 | b1.Xor(b1, b_minusone) 239 | 240 | set3Big(b1, b2, b3, t1, t2, t3) 241 | set3Int(f1, f2, f3, u1, u2, u3) 242 | 243 | b.Mod(b.Mul(t1, t2), t3) 244 | f.MulMod(u1, u2, u3) 245 | 246 | if !checkEq(b, f) { 247 | t.Fatalf("Expected equality:\nf1= 0x%x\nf2= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f2, f3, f, b) 248 | } 249 | 250 | set3Big(b1, b2, b3, t1, t2, t3) 251 | set3Int(f1, f2, f3, u1, u2, u3) 252 | 253 | b.Mod(b.Mul(t1, t3), t2) 254 | f.MulMod(u1, u3, u2) 255 | 256 | if !checkEq(b, f) { 257 | t.Fatalf("Expected equality:\nf1= 0x%x\nf3= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f3, f2, f, b) 258 | } 259 | 260 | set3Big(b1, b2, b3, t1, t2, t3) 261 | set3Int(f1, f2, f3, u1, u2, u3) 262 | 263 | b.Mod(b.Mul(t2, t1), t3) 264 | f.MulMod(u2, u1, u3) 265 | 266 | if !checkEq(b, f) { 267 | t.Fatalf("Expected equality:\nf2= 0x%x\nf1= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f1, f3, f, b) 268 | } 269 | 270 | set3Big(b1, b2, b3, t1, t2, t3) 271 | set3Int(f1, f2, f3, u1, u2, u3) 272 | 273 | b.Mod(b.Mul(t2, t3), t1) 274 | f.MulMod(u2, u3, u1) 275 | 276 | if !checkEq(b, f) { 277 | t.Fatalf("Expected equality:\nf2= 0x%x\nf3= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f1, f, b) 278 | } 279 | 280 | set3Big(b1, b2, b3, t1, t2, t3) 281 | set3Int(f1, f2, f3, u1, u2, u3) 282 | 283 | b.Mod(b.Mul(t3, t1), t2) 284 | f.MulMod(u3, u1, u2) 285 | 286 | if !checkEq(b, f) { 287 | t.Fatalf("Expected equality:\nf3= 0x%x\nf1= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f1, f2, f, b) 288 | } 289 | 290 | set3Big(b1, b2, b3, t1, t2, t3) 291 | set3Int(f1, f2, f3, u1, u2, u3) 292 | 293 | b.Mod(b.Mul(t3, t2), t1) 294 | f.MulMod(u3, u2, u1) 295 | 296 | if !checkEq(b, f) { 297 | t.Fatalf("Expected equality:\nf3= 0x%x\nf2= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f2, f1, f, b) 298 | } 299 | 300 | f1.Xor(f1, f_minusone) 301 | b1.Xor(b1, b_minusone) 302 | 303 | // Tests with one operand a power of 2 plus 1 304 | 305 | b1.Add(b1, b_one) 306 | f1.AddUint64(f1, 1) 307 | 308 | set3Big(b1, b2, b3, t1, t2, t3) 309 | set3Int(f1, f2, f3, u1, u2, u3) 310 | 311 | b.Mod(b.Mul(t1, t2), t3) 312 | f.MulMod(u1, u2, u3) 313 | 314 | if !checkEq(b, f) { 315 | t.Fatalf("Expected equality:\nf1= 0x%x\nf2= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f2, f3, f, b) 316 | } 317 | 318 | set3Big(b1, b2, b3, t1, t2, t3) 319 | set3Int(f1, f2, f3, u1, u2, u3) 320 | 321 | b.Mod(b.Mul(t1, t3), t2) 322 | f.MulMod(u1, u3, u2) 323 | 324 | if !checkEq(b, f) { 325 | t.Fatalf("Expected equality:\nf1= 0x%x\nf3= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f3, f2, f, b) 326 | } 327 | 328 | set3Big(b1, b2, b3, t1, t2, t3) 329 | set3Int(f1, f2, f3, u1, u2, u3) 330 | 331 | b.Mod(b.Mul(t2, t1), t3) 332 | f.MulMod(u2, u1, u3) 333 | 334 | if !checkEq(b, f) { 335 | t.Fatalf("Expected equality:\nf2= 0x%x\nf1= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f1, f3, f, b) 336 | } 337 | 338 | set3Big(b1, b2, b3, t1, t2, t3) 339 | set3Int(f1, f2, f3, u1, u2, u3) 340 | 341 | b.Mod(b.Mul(t2, t3), t1) 342 | f.MulMod(u2, u3, u1) 343 | 344 | if !checkEq(b, f) { 345 | t.Fatalf("Expected equality:\nf2= 0x%x\nf3= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f1, f, b) 346 | } 347 | 348 | set3Big(b1, b2, b3, t1, t2, t3) 349 | set3Int(f1, f2, f3, u1, u2, u3) 350 | 351 | b.Mod(b.Mul(t3, t1), t2) 352 | f.MulMod(u3, u1, u2) 353 | 354 | if !checkEq(b, f) { 355 | t.Fatalf("Expected equality:\nf3= 0x%x\nf1= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f1, f2, f, b) 356 | } 357 | 358 | set3Big(b1, b2, b3, t1, t2, t3) 359 | set3Int(f1, f2, f3, u1, u2, u3) 360 | 361 | b.Mod(b.Mul(t3, t2), t1) 362 | f.MulMod(u3, u2, u1) 363 | 364 | if !checkEq(b, f) { 365 | t.Fatalf("Expected equality:\nf3= 0x%x\nf2= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f2, f1, f, b) 366 | } 367 | 368 | // Tests with one operand a power of 2 minus 1 369 | 370 | if i == 0 { 371 | continue // skip zero operand 372 | } 373 | 374 | b1.Sub(b1, b_one) 375 | b1.Sub(b1, b_one) 376 | f1.SubUint64(f1, 2) 377 | 378 | set3Big(b1, b2, b3, t1, t2, t3) 379 | set3Int(f1, f2, f3, u1, u2, u3) 380 | 381 | b.Mod(b.Mul(t1, t2), t3) 382 | f.MulMod(u1, u2, u3) 383 | 384 | if !checkEq(b, f) { 385 | t.Fatalf("Expected equality:\nf1= 0x%x\nf2= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f2, f3, f, b) 386 | } 387 | 388 | set3Big(b1, b2, b3, t1, t2, t3) 389 | set3Int(f1, f2, f3, u1, u2, u3) 390 | 391 | b.Mod(b.Mul(t1, t3), t2) 392 | f.MulMod(u1, u3, u2) 393 | 394 | if !checkEq(b, f) { 395 | t.Fatalf("Expected equality:\nf1= 0x%x\nf3= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f3, f2, f, b) 396 | } 397 | 398 | set3Big(b1, b2, b3, t1, t2, t3) 399 | set3Int(f1, f2, f3, u1, u2, u3) 400 | 401 | b.Mod(b.Mul(t2, t1), t3) 402 | f.MulMod(u2, u1, u3) 403 | 404 | if !checkEq(b, f) { 405 | t.Fatalf("Expected equality:\nf2= 0x%x\nf1= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f1, f3, f, b) 406 | } 407 | 408 | set3Big(b1, b2, b3, t1, t2, t3) 409 | set3Int(f1, f2, f3, u1, u2, u3) 410 | 411 | b.Mod(b.Mul(t2, t3), t1) 412 | f.MulMod(u2, u3, u1) 413 | 414 | if !checkEq(b, f) { 415 | t.Fatalf("Expected equality:\nf2= 0x%x\nf3= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f1, f, b) 416 | } 417 | 418 | set3Big(b1, b2, b3, t1, t2, t3) 419 | set3Int(f1, f2, f3, u1, u2, u3) 420 | 421 | b.Mod(b.Mul(t3, t1), t2) 422 | f.MulMod(u3, u1, u2) 423 | 424 | if !checkEq(b, f) { 425 | t.Fatalf("Expected equality:\nf3= 0x%x\nf1= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f1, f2, f, b) 426 | } 427 | 428 | set3Big(b1, b2, b3, t1, t2, t3) 429 | set3Int(f1, f2, f3, u1, u2, u3) 430 | 431 | b.Mod(b.Mul(t3, t2), t1) 432 | f.MulMod(u3, u2, u1) 433 | 434 | if !checkEq(b, f) { 435 | t.Fatalf("Expected equality:\nf3= 0x%x\nf2= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f2, f1, f, b) 436 | } 437 | } 438 | } 439 | 440 | func TestRandomMulDivOverflow(t *testing.T) { 441 | for i := 0; i < 10000; i++ { 442 | b1, f1 := randNums() 443 | b2, f2 := randNums() 444 | b3, f3 := randNums() 445 | 446 | f1a, f2a, f3a := f1.Clone(), f2.Clone(), f3.Clone() 447 | 448 | _, overflow := f1.MulDivOverflow(f1, f2, f3) 449 | if b3.BitLen() == 0 { 450 | b1.SetInt64(0) 451 | } else { 452 | b1.Div(b1.Mul(b1, b2), b3) 453 | } 454 | 455 | if err := checkOverflow(b1, f1, overflow); err != nil { 456 | t.Fatal(err) 457 | } 458 | if eq := checkEq(b1, f1); !eq { 459 | t.Fatalf("Expected equality:\nf1= %x\nf2= %x\nf3= %x\n[ - ]==\nf= %x\nb= %x\n", f1a, f2a, f3a, f1, b1) 460 | } 461 | } 462 | } 463 | 464 | func TestRandomAbs(t *testing.T) { 465 | for i := 0; i < 10000; i++ { 466 | b, f1 := randHighNums() 467 | b2 := bigS256(big.NewInt(0).Set(b)) 468 | b2.Abs(b2) 469 | f1a := new(Int).Abs(f1) 470 | 471 | if eq := checkEq(b2, f1a); !eq { 472 | bf, _ := FromBig(b2) 473 | t.Fatalf("Expected equality:\nf1= %x\n[ abs ]==\nf = %x\nbf= %x\nb = %x\n", f1, f1a, bf, b2) 474 | } 475 | } 476 | } 477 | 478 | func TestUdivremQuick(t *testing.T) { 479 | var ( 480 | u = []uint64{1, 0, 0, 0, 0} 481 | expected = new(Int) 482 | rem Int 483 | ) 484 | udivrem([]uint64{}, u, &Int{0, 1, 0, 0}, &rem) 485 | copy(expected[:], u) 486 | if !rem.Eq(expected) { 487 | t.Errorf("Wrong remainder: %x, expected %x", rem, expected) 488 | } 489 | } 490 | 491 | func Test10KRandomSDiv(t *testing.T) { test10KRandom(t, "SDiv") } 492 | func Test10KRandomLsh(t *testing.T) { test10KRandom(t, "Lsh") } 493 | func Test10KRandomRsh(t *testing.T) { test10KRandom(t, "Rsh") } 494 | func Test10KRandomSRsh(t *testing.T) { test10KRandom(t, "SRsh") } 495 | func Test10KRandomExp(t *testing.T) { test10KRandom(t, "Exp") } 496 | 497 | func test10KRandom(t *testing.T, name string) { 498 | tc := lookupBinary(name) 499 | for i := 0; i < 10000; i++ { 500 | f1 := randNum() 501 | f2 := randNum() 502 | checkBinaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1, *f2) 503 | } 504 | } 505 | 506 | func TestSRsh(t *testing.T) { 507 | type testCase struct { 508 | arg string 509 | n uint64 510 | } 511 | testCases := []testCase{ 512 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 0}, 513 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 16}, 514 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 64}, 515 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 96}, 516 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 127}, 517 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 128}, 518 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 129}, 519 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 192}, 520 | {"0x8000000000000000000000000000000000000000000000000000000000000000", 254}, 521 | {"0x8000000000000000000000000000000000000000000000000000000000000000", 255}, 522 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 256}, 523 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 300}, 524 | {"0x7FFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 16}, 525 | {"0x7FFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 256}, 526 | } 527 | op := lookupBinary("SRsh") 528 | for _, tc := range testCases { 529 | arg := MustFromHex(tc.arg) 530 | n := NewInt(tc.n) 531 | checkBinaryOperation(t, op.name, op.u256Fn, op.bigFn, *arg, *n) 532 | } 533 | } 534 | 535 | func TestByte(t *testing.T) { 536 | input, err := FromHex("0x102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") 537 | if err != nil { 538 | t.Fatal(err) 539 | } 540 | for i := uint64(0); i < 35; i++ { 541 | var ( 542 | z = input.Clone() 543 | index = NewInt(i) 544 | have = z.Byte(index) 545 | want = NewInt(i) 546 | ) 547 | if i >= 32 { 548 | want.Clear() 549 | } 550 | if !have.Eq(want) { 551 | t.Fatalf("index %d: have %#x want %#x", i, have, want) 552 | } 553 | // Also check that we indeed modified the z 554 | if z != have { 555 | t.Fatalf("index %d: should return self %v %v", i, z, have) 556 | } 557 | } 558 | } 559 | 560 | func TestSignExtend(t *testing.T) { 561 | type testCase struct { 562 | arg string 563 | n uint64 564 | } 565 | testCases := []testCase{ 566 | {"10000000000000000", 2}, 567 | {"8080808080808080808080808080808080808080808080808080808080808080", 0}, 568 | {"8080808080808080808080808080808080808080808080808080808080808080", 1}, 569 | {"8080808080808080808080808080808080808080808080808080808080808080", 2}, 570 | {"8080808080808080808080808080808080808080808080808080808080808080", 3}, 571 | {"8080808080808080808080808080808080808080808080808080808080808080", 8}, 572 | {"8080808080808080808080808080808080808080808080808080808080808080", 18}, 573 | {"8080808080808080808080808080808080808080808080808080808080808080", 30}, 574 | {"8080808080808080808080808080808080808080808080808080808080808080", 31}, 575 | {"8080808080808080808080808080808080808080808080808080808080808080", 32}, 576 | {"4040404040404040404040404040404040404040404040404040404040404040", 0}, 577 | {"4040404040404040404040404040404040404040404040404040404040404040", 1}, 578 | {"4040404040404040404040404040404040404040404040404040404040404040", 15}, 579 | {"4040404040404040404040404040404040404040404040404040404040404040", 19}, 580 | {"4040404040404040404040404040404040404040404040404040404040404040", 30}, 581 | {"4040404040404040404040404040404040404040404040404040404040404040", 31}, 582 | {"4040404040404040404040404040404040404040404040404040404040404040", 32}, 583 | } 584 | op := lookupBinary("ExtendSign") 585 | for _, tc := range testCases { 586 | arg := new(Int).SetBytes(hex2Bytes(tc.arg)) 587 | n := new(Int).SetUint64(tc.n) 588 | checkBinaryOperation(t, op.name, op.u256Fn, op.bigFn, *arg, *n) 589 | } 590 | } 591 | 592 | func TestAddSubUint64(t *testing.T) { 593 | type testCase struct { 594 | arg string 595 | n uint64 596 | } 597 | testCases := []testCase{ 598 | {"0", 1}, 599 | {"1", 0}, 600 | {"1", 1}, 601 | {"1", 3}, 602 | {"0x10000000000000000", 1}, 603 | {"0x100000000000000000000000000000000", 1}, 604 | {"0", 0xffffffffffffffff}, 605 | {"1", 0xffffffff}, 606 | {"0xffffffffffffffff", 1}, 607 | {"0xffffffffffffffff", 0xffffffffffffffff}, 608 | {"0x10000000000000000", 1}, 609 | {"0xfffffffffffffffffffffffffffffffff", 1}, 610 | {"0xfffffffffffffffffffffffffffffffff", 2}, 611 | } 612 | 613 | for i := 0; i < len(testCases); i++ { 614 | tc := &testCases[i] 615 | bigArg, _ := new(big.Int).SetString(tc.arg, 0) 616 | arg, _ := FromBig(bigArg) 617 | { // SubUint64 618 | want, _ := FromBig(bigU256(new(big.Int).Sub(bigArg, new(big.Int).SetUint64(tc.n)))) 619 | have := new(Int).SetAllOne().SubUint64(arg, tc.n) 620 | if !have.Eq(want) { 621 | t.Logf("args: %s, %d\n", tc.arg, tc.n) 622 | t.Logf("want : %x\n", want) 623 | t.Logf("have : %x\n\n", have) 624 | t.Fail() 625 | } 626 | } 627 | { // AddUint64 628 | want, _ := FromBig(bigU256(new(big.Int).Add(bigArg, new(big.Int).SetUint64(tc.n)))) 629 | have := new(Int).AddUint64(arg, tc.n) 630 | if !have.Eq(want) { 631 | t.Logf("args: %s, %d\n", tc.arg, tc.n) 632 | t.Logf("want : %x\n", want) 633 | t.Logf("have : %x\n\n", have) 634 | t.Fail() 635 | } 636 | } 637 | } 638 | } 639 | 640 | func TestSGT(t *testing.T) { 641 | 642 | x := new(Int).SetBytes(hex2Bytes("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe")) 643 | y := new(Int).SetBytes(hex2Bytes("00")) 644 | actual := x.Sgt(y) 645 | if actual { 646 | t.Fatalf("Expected %v false", actual) 647 | } 648 | 649 | x = new(Int).SetBytes(hex2Bytes("00")) 650 | y = new(Int).SetBytes(hex2Bytes("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe")) 651 | actual = x.Sgt(y) 652 | if !actual { 653 | t.Fatalf("Expected %v true", actual) 654 | } 655 | } 656 | 657 | const ( 658 | // number of bits in a big.Word 659 | wordBits = 32 << (uint64(^big.Word(0)) >> 63) 660 | ) 661 | 662 | // TestFixedExpReusedArgs tests the cases in Exp() where the arguments (including result) alias the same objects. 663 | func TestFixedExpReusedArgs(t *testing.T) { 664 | f2 := Int{2, 0, 0, 0} 665 | f2.Exp(&f2, &f2) 666 | requireEq(t, big.NewInt(2*2), &f2, "") 667 | 668 | // TODO: This is tested in TestBinOp(). 669 | f3 := Int{3, 0, 0, 0} 670 | f4 := Int{4, 0, 0, 0} 671 | f3.Exp(&f4, &f3) 672 | requireEq(t, big.NewInt(4*4*4), &f3, "") 673 | 674 | // TODO: This is tested in TestBinOp(). 675 | f5 := Int{5, 0, 0, 0} 676 | f6 := Int{6, 0, 0, 0} 677 | f6.Exp(&f6, &f5) 678 | requireEq(t, big.NewInt(6*6*6*6*6), &f6, "") 679 | 680 | f3 = Int{3, 0, 0, 0} 681 | fr := new(Int).Exp(&f3, &f3) 682 | requireEq(t, big.NewInt(3*3*3), fr, "") 683 | } 684 | 685 | func TestPaddingRepresentation(t *testing.T) { 686 | a := big.NewInt(0xFF0AFcafe) 687 | aa := new(Int).SetUint64(0xFF0afcafe) 688 | bb := new(Int).SetBytes(a.Bytes()) 689 | if !aa.Eq(bb) { 690 | t.Fatal("aa != bb") 691 | } 692 | 693 | check := func(padded []byte, expectedHex string) { 694 | if expected := hex2Bytes(expectedHex); !bytes.Equal(padded, expected) { 695 | t.Errorf("incorrect padded bytes: %x, expected: %x", padded, expected) 696 | } 697 | } 698 | 699 | check(aa.PaddedBytes(32), "0000000000000000000000000000000000000000000000000000000ff0afcafe") 700 | check(aa.PaddedBytes(20), "0000000000000000000000000000000ff0afcafe") 701 | check(aa.PaddedBytes(40), "00000000000000000000000000000000000000000000000000000000000000000000000ff0afcafe") 702 | 703 | bytearr := hex2Bytes("0e320219838e859b2f9f18b72e3d4073ca50b37d") 704 | a = new(big.Int).SetBytes(bytearr) 705 | aa = new(Int).SetBytes(bytearr) 706 | bb = new(Int).SetBytes(a.Bytes()) 707 | if !aa.Eq(bb) { 708 | t.Fatal("aa != bb") 709 | } 710 | 711 | check(aa.PaddedBytes(32), "0000000000000000000000000e320219838e859b2f9f18b72e3d4073ca50b37d") 712 | check(aa.PaddedBytes(20), "0e320219838e859b2f9f18b72e3d4073ca50b37d") 713 | check(aa.PaddedBytes(40), "00000000000000000000000000000000000000000e320219838e859b2f9f18b72e3d4073ca50b37d") 714 | } 715 | 716 | func TestWriteToSlice(t *testing.T) { 717 | x1 := hex2Bytes("fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611") 718 | 719 | a := big.NewInt(0).SetBytes(x1) 720 | fa, _ := FromBig(a) 721 | 722 | dest := make([]byte, 32) 723 | fa.WriteToSlice(dest) 724 | if !bytes.Equal(dest, x1) { 725 | t.Errorf("got %x, expected %x", dest, x1) 726 | } 727 | 728 | fb := new(Int) 729 | exp := make([]byte, 32) 730 | fb.WriteToSlice(dest) 731 | if !bytes.Equal(dest, exp) { 732 | t.Errorf("got %x, expected %x", dest, exp) 733 | } 734 | // a too small buffer 735 | // Should fill the lower parts, masking upper bytes 736 | exp = hex2Bytes("683fd1e870eec79504c60144cc7f5fc2bad1e611") 737 | dest = make([]byte, 20) 738 | fa.WriteToSlice(dest) 739 | if !bytes.Equal(dest, exp) { 740 | t.Errorf("got %x, expected %x", dest, exp) 741 | } 742 | 743 | // a too large buffer, already filled with stuff 744 | // Should fill the leftmost 32 bytes, not touch the other things 745 | dest = hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") 746 | exp = hex2Bytes("fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611ffffffffffffffff") 747 | 748 | fa.WriteToSlice(dest) 749 | if !bytes.Equal(dest, exp) { 750 | t.Errorf("got %x, expected %x", dest, x1) 751 | } 752 | 753 | // an empty slice, no panics please 754 | dest = []byte{} 755 | exp = []byte{} 756 | 757 | fa.WriteToSlice(dest) 758 | if !bytes.Equal(dest, exp) { 759 | t.Errorf("got %x, expected %x", dest, x1) 760 | } 761 | 762 | } 763 | 764 | func TestInt_WriteToArray(t *testing.T) { 765 | x1 := hex2Bytes("0102030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611") 766 | a := big.NewInt(0).SetBytes(x1) 767 | fa, _ := FromBig(a) 768 | 769 | { 770 | dest := [20]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 771 | fa.WriteToArray20(&dest) 772 | exp := hex2Bytes("0d0ed1e870eec79504c60144cc7f5fc2bad1e611") 773 | if !bytes.Equal(dest[:], exp) { 774 | t.Errorf("got %x, expected %x", dest, exp) 775 | } 776 | } 777 | { 778 | dest := [32]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 779 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 780 | fa.WriteToArray32(&dest) 781 | exp := hex2Bytes("0102030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611") 782 | if !bytes.Equal(dest[:], exp) { 783 | t.Errorf("got %x, expected %x", dest, exp) 784 | } 785 | } 786 | { // A 36-byte slice: the first 32 bytes are overwritten 787 | dest := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 788 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 789 | fa.PutUint256(dest) 790 | exp := hex2Bytes("0102030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611ffffffff") 791 | if !bytes.Equal(dest[:], exp) { 792 | t.Errorf("got %x, expected %x", dest, exp) 793 | } 794 | } 795 | } 796 | 797 | type gethAddress [20]byte 798 | 799 | // SetBytes sets the address to the value of b. 800 | // If b is larger than len(a) it will panic. 801 | func (a *gethAddress) setBytes(b []byte) { 802 | if len(b) > len(a) { 803 | b = b[len(b)-20:] 804 | } 805 | copy(a[20-len(b):], b) 806 | } 807 | 808 | // BytesToAddress returns Address with value b. 809 | // If b is larger than len(h), b will be cropped from the left. 810 | func bytesToAddress(b []byte) gethAddress { 811 | var a gethAddress 812 | a.setBytes(b) 813 | return a 814 | } 815 | 816 | type gethHash [32]byte 817 | 818 | // SetBytes sets the address to the value of b. 819 | // If b is larger than len(a) it will panic. 820 | func (a *gethHash) setBytes(b []byte) { 821 | if len(b) > len(a) { 822 | b = b[len(b)-32:] 823 | } 824 | copy(a[32-len(b):], b) 825 | } 826 | 827 | // BytesToHash returns gethHash with value b. 828 | // If b is larger than len(h), b will be cropped from the left. 829 | func bytesToHash(b []byte) gethHash { 830 | var a gethHash 831 | a.setBytes(b) 832 | return a 833 | } 834 | 835 | func TestByteRepresentation(t *testing.T) { 836 | for i, tt := range []string{ 837 | "1337fafafa0e320219838e859b2f9f18b72e3d4073ca50b37d", 838 | "fafafa0e320219838e859b2f9f18b72e3d4073ca50b37d", 839 | "0e320219838e859b2f9f18b72e3d4073ca50b37d", 840 | "320219838e859b2f9f18b72e3d4073ca50b37d", 841 | "838e859b2f9f18b72e3d4073ca50b37d", 842 | "38e859b2f9f18b72e3d4073ca50b37d", 843 | "f18b72e3d4073ca50b37d", 844 | "b37d", 845 | "01", 846 | "", 847 | "00", 848 | } { 849 | bytearr := hex2Bytes(tt) 850 | // big.Int -> address, hash 851 | a := big.NewInt(0).SetBytes(bytearr) 852 | want20 := bytesToAddress(a.Bytes()) 853 | want32 := bytesToHash(a.Bytes()) 854 | 855 | // uint256.Int -> address 856 | b := new(Int).SetBytes(bytearr) 857 | have20 := gethAddress(b.Bytes20()) 858 | have32 := gethHash(b.Bytes32()) 859 | 860 | if have, want := want20, have20; have != want { 861 | t.Errorf("test %d: have %x want %x", i, have, want) 862 | } 863 | if have, want := want32, have32; have != want { 864 | t.Errorf("test %d: have %x want %x", i, have, want) 865 | } 866 | } 867 | } 868 | 869 | func testLog10(t *testing.T, z *Int) { 870 | want := uint(len(z.Dec())) 871 | if want > 0 { 872 | want-- 873 | } 874 | if have := z.Log10(); have != want { 875 | t.Errorf("%s (%s): have %v want %v", z.Hex(), z.Dec(), have, want) 876 | } 877 | } 878 | 879 | func TestLog10(t *testing.T) { 880 | testLog10(t, new(Int)) 881 | for i := uint(0); i < 255; i++ { 882 | z := NewInt(1) 883 | testLog10(t, z.Lsh(z, i)) 884 | if i != 0 { 885 | testLog10(t, new(Int).SubUint64(z, 1)) 886 | } 887 | } 888 | z := NewInt(1) 889 | ten := NewInt(10) 890 | for i := uint(0); i < 80; i++ { 891 | testLog10(t, z.Mul(z, ten)) 892 | testLog10(t, new(Int).SubUint64(z, 1)) 893 | } 894 | } 895 | 896 | func FuzzLog10(f *testing.F) { 897 | f.Fuzz(func(t *testing.T, aa, bb, cc, dd uint64) { 898 | testLog10(t, &Int{aa, bb, cc, dd}) 899 | }) 900 | } 901 | 902 | func BenchmarkLog10(b *testing.B) { 903 | var u256Ints []*Int 904 | var bigints []*big.Int 905 | 906 | for i := uint(0); i < 255; i++ { 907 | a := NewInt(1) 908 | a.Lsh(a, i) 909 | u256Ints = append(u256Ints, a) 910 | bigints = append(bigints, a.ToBig()) 911 | } 912 | b.Run("Log10/uint256", func(b *testing.B) { 913 | b.ReportAllocs() 914 | for i := 0; i < b.N; i++ { 915 | for _, z := range u256Ints { 916 | _ = z.Log10() 917 | } 918 | } 919 | }) 920 | b.Run("Log10/big", func(b *testing.B) { 921 | b.ReportAllocs() 922 | for i := 0; i < b.N; i++ { 923 | for _, z := range bigints { 924 | f, _ := new(big.Float).SetInt(z).Float64() 925 | _ = int(math.Log10(f)) 926 | } 927 | } 928 | }) 929 | } 930 | 931 | func TestCmpUint64(t *testing.T) { 932 | check := func(z *Int, x uint64) { 933 | want := z.ToBig().Cmp(new(big.Int).SetUint64(x)) 934 | have := z.CmpUint64(x) 935 | if have != want { 936 | t.Errorf("%s.CmpUint64( %x ) : have %v want %v", z.Hex(), x, have, want) 937 | } 938 | } 939 | for i := uint(0); i < 255; i++ { 940 | z := NewInt(1) 941 | z.Lsh(z, i) 942 | check(z, new(Int).Set(z).Uint64()) // z, z 943 | check(z, new(Int).AddUint64(z, 1).Uint64()) // z, z + 1 944 | check(z, new(Int).SubUint64(z, 1).Uint64()) // z, z - 1 945 | check(z, new(big.Int).Rsh(new(Int).Set(z).ToBig(), 64).Uint64()) // z, z >> 64 946 | } 947 | } 948 | 949 | func TestCmpBig(t *testing.T) { 950 | check := func(z *Int, x *big.Int) { 951 | want := z.ToBig().Cmp(x) 952 | have := z.CmpBig(x) 953 | if have != want { 954 | t.Errorf("%s.CmpBig( %x ) : have %v want %v", z.Hex(), x, have, want) 955 | } 956 | } 957 | for i := uint(0); i < 255; i++ { 958 | z := NewInt(1) 959 | z.Lsh(z, i) 960 | check(z, new(Int).Set(z).ToBig()) // z, z 961 | check(z, new(Int).AddUint64(z, 1).ToBig()) // z, z + 1 962 | check(z, new(Int).SubUint64(z, 1).ToBig()) // z, z - 1 963 | check(z, new(big.Int).Neg(new(Int).Set(z).ToBig())) // z, -z 964 | check(z, new(big.Int).Lsh(new(Int).Set(z).ToBig(), 256)) // z, z << 256 965 | } 966 | } 967 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------