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