github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/common/math/big.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:32</date> 10 //</624342609459941376> 11 12 13 //包数学提供整数数学实用程序。 14 package math 15 16 import ( 17 "fmt" 18 "math/big" 19 ) 20 21 //各种大整数限制值。 22 var ( 23 tt255 = BigPow(2, 255) 24 tt256 = BigPow(2, 256) 25 tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1)) 26 tt63 = BigPow(2, 63) 27 MaxBig256 = new(big.Int).Set(tt256m1) 28 MaxBig63 = new(big.Int).Sub(tt63, big.NewInt(1)) 29 ) 30 31 const ( 32 //一个大字的位数。 33 wordBits = 32 << (uint64(^big.Word(0)) >> 63) 34 //一个大的.word中的字节数 35 wordBytes = wordBits / 8 36 ) 37 38 //hexordecimal256将big.int封送为十六进制或十进制。 39 type HexOrDecimal256 big.Int 40 41 //UnmarshalText实现encoding.textUnmarshaller。 42 func (i *HexOrDecimal256) UnmarshalText(input []byte) error { 43 bigint, ok := ParseBig256(string(input)) 44 if !ok { 45 return fmt.Errorf("invalid hex or decimal integer %q", input) 46 } 47 *i = HexOrDecimal256(*bigint) 48 return nil 49 } 50 51 //MarshalText实现Encoding.TextMarshaler。 52 func (i *HexOrDecimal256) MarshalText() ([]byte, error) { 53 if i == nil { 54 return []byte("0x0"), nil 55 } 56 return []byte(fmt.Sprintf("%#x", (*big.Int)(i))), nil 57 } 58 59 //parseBig256以十进制或十六进制语法解析为256位整数。 60 //可接受前导零。空字符串解析为零。 61 func ParseBig256(s string) (*big.Int, bool) { 62 if s == "" { 63 return new(big.Int), true 64 } 65 var bigint *big.Int 66 var ok bool 67 if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") { 68 bigint, ok = new(big.Int).SetString(s[2:], 16) 69 } else { 70 bigint, ok = new(big.Int).SetString(s, 10) 71 } 72 if ok && bigint.BitLen() > 256 { 73 bigint, ok = nil, false 74 } 75 return bigint, ok 76 } 77 78 //mustParseBig256解析为256位大整数,如果字符串无效,则会恐慌。 79 func MustParseBig256(s string) *big.Int { 80 v, ok := ParseBig256(s) 81 if !ok { 82 panic("invalid 256 bit integer: " + s) 83 } 84 return v 85 } 86 87 //bigpow返回一个**b作为大整数。 88 func BigPow(a, b int64) *big.Int { 89 r := big.NewInt(a) 90 return r.Exp(r, big.NewInt(b), nil) 91 } 92 93 // 94 func BigMax(x, y *big.Int) *big.Int { 95 if x.Cmp(y) < 0 { 96 return y 97 } 98 return x 99 } 100 101 //bigmin返回x或y中的较小值。 102 func BigMin(x, y *big.Int) *big.Int { 103 if x.Cmp(y) > 0 { 104 return y 105 } 106 return x 107 } 108 109 //firstbitset返回v中第一个1位的索引,从lsb开始计数。 110 func FirstBitSet(v *big.Int) int { 111 for i := 0; i < v.BitLen(); i++ { 112 if v.Bit(i) > 0 { 113 return i 114 } 115 } 116 return v.BitLen() 117 } 118 119 // 120 //切片中至少有n个字节。 121 func PaddedBigBytes(bigint *big.Int, n int) []byte { 122 if bigint.BitLen()/8 >= n { 123 return bigint.Bytes() 124 } 125 ret := make([]byte, n) 126 ReadBits(bigint, ret) 127 return ret 128 } 129 130 //bigendianbyteat返回位置n处的字节, 131 //在big-endian编码中 132 //因此n==0返回最低有效字节 133 func bigEndianByteAt(bigint *big.Int, n int) byte { 134 words := bigint.Bits() 135 //检查字节将驻留的字桶 136 i := n / wordBytes 137 if i >= len(words) { 138 return byte(0) 139 } 140 word := words[i] 141 //字节偏移量 142 shift := 8 * uint(n%wordBytes) 143 144 return byte(word >> shift) 145 } 146 147 //byte返回位置n处的字节, 148 //以小尾数编码提供的padLength。 149 //n==0返回最高位 150 //示例:Bigint“5”,PadLength 32,n=31=>5 151 func Byte(bigint *big.Int, padlength, n int) byte { 152 if n >= padlength { 153 return byte(0) 154 } 155 return bigEndianByteAt(bigint, padlength-1-n) 156 } 157 158 //readbits将bigint的绝对值编码为big-endian字节。呼叫者必须确保 159 //那个流浪汉有足够的空间。如果buf太短,结果将不完整。 160 func ReadBits(bigint *big.Int, buf []byte) { 161 i := len(buf) 162 for _, d := range bigint.Bits() { 163 for j := 0; j < wordBytes && i > 0; j++ { 164 i-- 165 buf[i] = byte(d) 166 d >>= 8 167 } 168 } 169 } 170 171 //U256编码为256位2的补码。这项行动具有破坏性。 172 func U256(x *big.Int) *big.Int { 173 return x.And(x, tt256m1) 174 } 175 176 //s256将x解释为2的补码。 177 // 178 // 179 //s256(0)=0 180 //s256(1)=1 181 //S256(2**255)=-2**255 182 //s256(2**256-1)=-1 183 func S256(x *big.Int) *big.Int { 184 if x.Cmp(tt255) < 0 { 185 return x 186 } 187 return new(big.Int).Sub(x, tt256) 188 } 189 190 //exp通过平方实现求幂。 191 //exp返回新分配的大整数,不更改 192 //基或指数。结果被截断为256位。 193 // 194 //由@karalabe和@chfast提供 195 func Exp(base, exponent *big.Int) *big.Int { 196 result := big.NewInt(1) 197 198 for _, word := range exponent.Bits() { 199 for i := 0; i < wordBits; i++ { 200 if word&1 == 1 { 201 U256(result.Mul(result, base)) 202 } 203 U256(base.Mul(base, base)) 204 word >>= 1 205 } 206 } 207 return result 208 } 209