github.com/Finschia/finschia-sdk@v0.48.1/types/int.go (about) 1 package types 2 3 import ( 4 "encoding" 5 "encoding/json" 6 "fmt" 7 "math/big" 8 "testing" 9 ) 10 11 const maxBitLen = 256 12 13 func newIntegerFromString(s string) (*big.Int, bool) { 14 return new(big.Int).SetString(s, 0) 15 } 16 17 func equal(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == 0 } 18 19 func gt(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == 1 } 20 21 func gte(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) >= 0 } 22 23 func lt(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == -1 } 24 25 func lte(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) <= 0 } 26 27 func add(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Add(i, i2) } 28 29 func sub(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Sub(i, i2) } 30 31 func mul(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Mul(i, i2) } 32 33 func div(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Quo(i, i2) } 34 35 func mod(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Mod(i, i2) } 36 37 func neg(i *big.Int) *big.Int { return new(big.Int).Neg(i) } 38 39 func abs(i *big.Int) *big.Int { return new(big.Int).Abs(i) } 40 41 func min(i *big.Int, i2 *big.Int) *big.Int { 42 if i.Cmp(i2) == 1 { 43 return new(big.Int).Set(i2) 44 } 45 46 return new(big.Int).Set(i) 47 } 48 49 func max(i *big.Int, i2 *big.Int) *big.Int { 50 if i.Cmp(i2) == -1 { 51 return new(big.Int).Set(i2) 52 } 53 54 return new(big.Int).Set(i) 55 } 56 57 func unmarshalText(i *big.Int, text string) error { 58 if err := i.UnmarshalText([]byte(text)); err != nil { 59 return err 60 } 61 62 if i.BitLen() > maxBitLen { 63 return fmt.Errorf("integer out of range: %s", text) 64 } 65 66 return nil 67 } 68 69 var _ CustomProtobufType = (*Int)(nil) 70 71 // Int wraps big.Int with a 257 bit range bound 72 // Checks overflow, underflow and division by zero 73 // Exists in range from -(2^256 - 1) to 2^256 - 1 74 type Int struct { 75 i *big.Int 76 } 77 78 // BigInt converts Int to big.Int 79 func (i Int) BigInt() *big.Int { 80 if i.IsNil() { 81 return nil 82 } 83 return new(big.Int).Set(i.i) 84 } 85 86 // IsNil returns true if Int is uninitialized 87 func (i Int) IsNil() bool { 88 return i.i == nil 89 } 90 91 // NewInt constructs Int from int64 92 func NewInt(n int64) Int { 93 return Int{big.NewInt(n)} 94 } 95 96 // NewIntFromUint64 constructs an Int from a uint64. 97 func NewIntFromUint64(n uint64) Int { 98 b := big.NewInt(0) 99 b.SetUint64(n) 100 return Int{b} 101 } 102 103 // NewIntFromBigInt constructs Int from big.Int. If the provided big.Int is nil, 104 // it returns an empty instance. This function panics if the bit length is > 256. 105 func NewIntFromBigInt(i *big.Int) Int { 106 if i == nil { 107 return Int{} 108 } 109 110 if i.BitLen() > maxBitLen { 111 panic("NewIntFromBigInt() out of bound") 112 } 113 return Int{i} 114 } 115 116 // NewIntFromString constructs Int from string 117 func NewIntFromString(s string) (res Int, ok bool) { 118 i, ok := newIntegerFromString(s) 119 if !ok { 120 return 121 } 122 // Check overflow 123 if i.BitLen() > maxBitLen { 124 ok = false 125 return 126 } 127 return Int{i}, true 128 } 129 130 // NewIntWithDecimal constructs Int with decimal 131 // Result value is n*10^dec 132 func NewIntWithDecimal(n int64, dec int) Int { 133 if dec < 0 { 134 panic("NewIntWithDecimal() decimal is negative") 135 } 136 exp := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(dec)), nil) 137 i := new(big.Int) 138 i.Mul(big.NewInt(n), exp) 139 140 // Check overflow 141 if i.BitLen() > maxBitLen { 142 panic("NewIntWithDecimal() out of bound") 143 } 144 return Int{i} 145 } 146 147 // ZeroInt returns Int value with zero 148 func ZeroInt() Int { return Int{big.NewInt(0)} } 149 150 // OneInt returns Int value with one 151 func OneInt() Int { return Int{big.NewInt(1)} } 152 153 // ToDec converts Int to Dec 154 func (i Int) ToDec() Dec { 155 return NewDecFromInt(i) 156 } 157 158 // Int64 converts Int to int64 159 // Panics if the value is out of range 160 func (i Int) Int64() int64 { 161 if !i.i.IsInt64() { 162 panic("Int64() out of bound") 163 } 164 return i.i.Int64() 165 } 166 167 // IsInt64 returns true if Int64() not panics 168 func (i Int) IsInt64() bool { 169 return i.i.IsInt64() 170 } 171 172 // Uint64 converts Int to uint64 173 // Panics if the value is out of range 174 func (i Int) Uint64() uint64 { 175 if !i.i.IsUint64() { 176 panic("Uint64() out of bounds") 177 } 178 return i.i.Uint64() 179 } 180 181 // IsUint64 returns true if Uint64() not panics 182 func (i Int) IsUint64() bool { 183 return i.i.IsUint64() 184 } 185 186 // IsZero returns true if Int is zero 187 func (i Int) IsZero() bool { 188 return i.i.Sign() == 0 189 } 190 191 // IsNegative returns true if Int is negative 192 func (i Int) IsNegative() bool { 193 return i.i.Sign() == -1 194 } 195 196 // IsPositive returns true if Int is positive 197 func (i Int) IsPositive() bool { 198 return i.i.Sign() == 1 199 } 200 201 // Sign returns sign of Int 202 func (i Int) Sign() int { 203 return i.i.Sign() 204 } 205 206 // Equal compares two Ints 207 func (i Int) Equal(i2 Int) bool { 208 return equal(i.i, i2.i) 209 } 210 211 // GT returns true if first Int is greater than second 212 func (i Int) GT(i2 Int) bool { 213 return gt(i.i, i2.i) 214 } 215 216 // GTE returns true if receiver Int is greater than or equal to the parameter 217 // Int. 218 func (i Int) GTE(i2 Int) bool { 219 return gte(i.i, i2.i) 220 } 221 222 // LT returns true if first Int is lesser than second 223 func (i Int) LT(i2 Int) bool { 224 return lt(i.i, i2.i) 225 } 226 227 // LTE returns true if first Int is less than or equal to second 228 func (i Int) LTE(i2 Int) bool { 229 return lte(i.i, i2.i) 230 } 231 232 // Add adds Int from another 233 func (i Int) Add(i2 Int) (res Int) { 234 res = Int{add(i.i, i2.i)} 235 // Check overflow 236 if res.i.BitLen() > maxBitLen { 237 panic("Int overflow") 238 } 239 return 240 } 241 242 // AddRaw adds int64 to Int 243 func (i Int) AddRaw(i2 int64) Int { 244 return i.Add(NewInt(i2)) 245 } 246 247 // Sub subtracts Int from another 248 func (i Int) Sub(i2 Int) (res Int) { 249 res = Int{sub(i.i, i2.i)} 250 // Check overflow 251 if res.i.BitLen() > maxBitLen { 252 panic("Int overflow") 253 } 254 return 255 } 256 257 // SubRaw subtracts int64 from Int 258 func (i Int) SubRaw(i2 int64) Int { 259 return i.Sub(NewInt(i2)) 260 } 261 262 // Mul multiples two Ints 263 func (i Int) Mul(i2 Int) (res Int) { 264 // Check overflow 265 if i.i.BitLen()+i2.i.BitLen()-1 > maxBitLen { 266 panic("Int overflow") 267 } 268 res = Int{mul(i.i, i2.i)} 269 // Check overflow if sign of both are same 270 if res.i.BitLen() > maxBitLen { 271 panic("Int overflow") 272 } 273 return 274 } 275 276 // MulRaw multipies Int and int64 277 func (i Int) MulRaw(i2 int64) Int { 278 return i.Mul(NewInt(i2)) 279 } 280 281 // Quo divides Int with Int 282 func (i Int) Quo(i2 Int) (res Int) { 283 // Check division-by-zero 284 if i2.i.Sign() == 0 { 285 panic("Division by zero") 286 } 287 return Int{div(i.i, i2.i)} 288 } 289 290 // QuoRaw divides Int with int64 291 func (i Int) QuoRaw(i2 int64) Int { 292 return i.Quo(NewInt(i2)) 293 } 294 295 // Mod returns remainder after dividing with Int 296 func (i Int) Mod(i2 Int) Int { 297 if i2.Sign() == 0 { 298 panic("division-by-zero") 299 } 300 return Int{mod(i.i, i2.i)} 301 } 302 303 // ModRaw returns remainder after dividing with int64 304 func (i Int) ModRaw(i2 int64) Int { 305 return i.Mod(NewInt(i2)) 306 } 307 308 // Neg negates Int 309 func (i Int) Neg() (res Int) { 310 return Int{neg(i.i)} 311 } 312 313 // Abs returns the absolute value of Int. 314 func (i Int) Abs() Int { 315 return Int{abs(i.i)} 316 } 317 318 // return the minimum of the ints 319 func MinInt(i1, i2 Int) Int { 320 return Int{min(i1.BigInt(), i2.BigInt())} 321 } 322 323 // MaxInt returns the maximum between two integers. 324 func MaxInt(i, i2 Int) Int { 325 return Int{max(i.BigInt(), i2.BigInt())} 326 } 327 328 // Human readable string 329 func (i Int) String() string { 330 return i.i.String() 331 } 332 333 // MarshalJSON defines custom encoding scheme 334 func (i Int) MarshalJSON() ([]byte, error) { 335 if i.i == nil { // Necessary since default Uint initialization has i.i as nil 336 i.i = new(big.Int) 337 } 338 return marshalJSON(i.i) 339 } 340 341 // UnmarshalJSON defines custom decoding scheme 342 func (i *Int) UnmarshalJSON(bz []byte) error { 343 if i.i == nil { // Necessary since default Int initialization has i.i as nil 344 i.i = new(big.Int) 345 } 346 return unmarshalJSON(i.i, bz) 347 } 348 349 // MarshalJSON for custom encoding scheme 350 // Must be encoded as a string for JSON precision 351 func marshalJSON(i encoding.TextMarshaler) ([]byte, error) { 352 text, err := i.MarshalText() 353 if err != nil { 354 return nil, err 355 } 356 357 return json.Marshal(string(text)) 358 } 359 360 // UnmarshalJSON for custom decoding scheme 361 // Must be encoded as a string for JSON precision 362 func unmarshalJSON(i *big.Int, bz []byte) error { 363 var text string 364 if err := json.Unmarshal(bz, &text); err != nil { 365 return err 366 } 367 368 return unmarshalText(i, text) 369 } 370 371 // MarshalYAML returns the YAML representation. 372 func (i Int) MarshalYAML() (interface{}, error) { 373 return i.String(), nil 374 } 375 376 // Marshal implements the gogo proto custom type interface. 377 func (i Int) Marshal() ([]byte, error) { 378 if i.i == nil { 379 i.i = new(big.Int) 380 } 381 return i.i.MarshalText() 382 } 383 384 // MarshalTo implements the gogo proto custom type interface. 385 func (i *Int) MarshalTo(data []byte) (n int, err error) { 386 if i.i == nil { 387 i.i = new(big.Int) 388 } 389 if i.i.BitLen() == 0 { // The value 0 390 copy(data, []byte{0x30}) 391 return 1, nil 392 } 393 394 bz, err := i.Marshal() 395 if err != nil { 396 return 0, err 397 } 398 399 copy(data, bz) 400 return len(bz), nil 401 } 402 403 // Unmarshal implements the gogo proto custom type interface. 404 func (i *Int) Unmarshal(data []byte) error { 405 if len(data) == 0 { 406 i = nil 407 return nil 408 } 409 410 if i.i == nil { 411 i.i = new(big.Int) 412 } 413 414 if err := i.i.UnmarshalText(data); err != nil { 415 return err 416 } 417 418 if i.i.BitLen() > maxBitLen { 419 return fmt.Errorf("integer out of range; got: %d, max: %d", i.i.BitLen(), maxBitLen) 420 } 421 422 return nil 423 } 424 425 // Size implements the gogo proto custom type interface. 426 func (i *Int) Size() int { 427 bz, _ := i.Marshal() 428 return len(bz) 429 } 430 431 // Override Amino binary serialization by proxying to protobuf. 432 func (i Int) MarshalAmino() ([]byte, error) { return i.Marshal() } 433 func (i *Int) UnmarshalAmino(bz []byte) error { return i.Unmarshal(bz) } 434 435 // intended to be used with require/assert: require.True(IntEq(...)) 436 func IntEq(t *testing.T, exp, got Int) (*testing.T, bool, string, string, string) { 437 return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp.String(), got.String() 438 } 439 440 func (ip IntProto) String() string { 441 return ip.Int.String() 442 }