github.com/Finschia/finschia-sdk@v0.48.1/types/uint.go (about) 1 package types 2 3 import ( 4 "errors" 5 "fmt" 6 "math/big" 7 ) 8 9 // Uint wraps integer with 256 bit range bound 10 // Checks overflow, underflow and division by zero 11 // Exists in range from 0 to 2^256-1 12 type Uint struct { 13 i *big.Int 14 } 15 16 // BigInt converts Uint to big.Int 17 func (u Uint) BigInt() *big.Int { 18 return new(big.Int).Set(u.i) 19 } 20 21 // NewUintFromBigUint constructs Uint from big.Uint 22 func NewUintFromBigInt(i *big.Int) Uint { 23 u, err := checkNewUint(i) 24 if err != nil { 25 panic(fmt.Errorf("overflow: %s", err)) 26 } 27 return u 28 } 29 30 // NewUint constructs Uint from int64 31 func NewUint(n uint64) Uint { 32 i := new(big.Int) 33 i.SetUint64(n) 34 return NewUintFromBigInt(i) 35 } 36 37 // NewUintFromString constructs Uint from string 38 func NewUintFromString(s string) Uint { 39 u, err := ParseUint(s) 40 if err != nil { 41 panic(err) 42 } 43 return u 44 } 45 46 // ZeroUint returns unsigned zero. 47 func ZeroUint() Uint { return Uint{big.NewInt(0)} } 48 49 // OneUint returns Uint value with one. 50 func OneUint() Uint { return Uint{big.NewInt(1)} } 51 52 var _ CustomProtobufType = (*Uint)(nil) 53 54 // Uint64 converts Uint to uint64 55 // Panics if the value is out of range 56 func (u Uint) Uint64() uint64 { 57 if !u.i.IsUint64() { 58 panic("Uint64() out of bound") 59 } 60 return u.i.Uint64() 61 } 62 63 // IsZero returns 1 if the uint equals to 0. 64 func (u Uint) IsZero() bool { return u.Equal(ZeroUint()) } 65 66 // Equal compares two Uints 67 func (u Uint) Equal(u2 Uint) bool { return equal(u.i, u2.i) } 68 69 // GT returns true if first Uint is greater than second 70 func (u Uint) GT(u2 Uint) bool { return gt(u.i, u2.i) } 71 72 // GTE returns true if first Uint is greater than second 73 func (u Uint) GTE(u2 Uint) bool { return u.GT(u2) || u.Equal(u2) } 74 75 // LT returns true if first Uint is lesser than second 76 func (u Uint) LT(u2 Uint) bool { return lt(u.i, u2.i) } 77 78 // LTE returns true if first Uint is lesser than or equal to the second 79 func (u Uint) LTE(u2 Uint) bool { return !u.GT(u2) } 80 81 // Add adds Uint from another 82 func (u Uint) Add(u2 Uint) Uint { return NewUintFromBigInt(new(big.Int).Add(u.i, u2.i)) } 83 84 // Add convert uint64 and add it to Uint 85 func (u Uint) AddUint64(u2 uint64) Uint { return u.Add(NewUint(u2)) } 86 87 // Sub adds Uint from another 88 func (u Uint) Sub(u2 Uint) Uint { return NewUintFromBigInt(new(big.Int).Sub(u.i, u2.i)) } 89 90 // SubUint64 adds Uint from another 91 func (u Uint) SubUint64(u2 uint64) Uint { return u.Sub(NewUint(u2)) } 92 93 // Mul multiplies two Uints 94 func (u Uint) Mul(u2 Uint) (res Uint) { 95 return NewUintFromBigInt(new(big.Int).Mul(u.i, u2.i)) 96 } 97 98 // Mul multiplies two Uints 99 func (u Uint) MulUint64(u2 uint64) (res Uint) { return u.Mul(NewUint(u2)) } 100 101 // Quo divides Uint with Uint 102 func (u Uint) Quo(u2 Uint) (res Uint) { return NewUintFromBigInt(div(u.i, u2.i)) } 103 104 // Mod returns remainder after dividing with Uint 105 func (u Uint) Mod(u2 Uint) Uint { 106 if u2.IsZero() { 107 panic("division-by-zero") 108 } 109 return Uint{mod(u.i, u2.i)} 110 } 111 112 // Incr increments the Uint by one. 113 func (u Uint) Incr() Uint { 114 return u.Add(OneUint()) 115 } 116 117 // Decr decrements the Uint by one. 118 // Decr will panic if the Uint is zero. 119 func (u Uint) Decr() Uint { 120 return u.Sub(OneUint()) 121 } 122 123 // Quo divides Uint with uint64 124 func (u Uint) QuoUint64(u2 uint64) Uint { return u.Quo(NewUint(u2)) } 125 126 // Return the minimum of the Uints 127 func MinUint(u1, u2 Uint) Uint { return NewUintFromBigInt(min(u1.i, u2.i)) } 128 129 // Return the maximum of the Uints 130 func MaxUint(u1, u2 Uint) Uint { return NewUintFromBigInt(max(u1.i, u2.i)) } 131 132 // Human readable string 133 func (u Uint) String() string { return u.i.String() } 134 135 // MarshalJSON defines custom encoding scheme 136 func (u Uint) MarshalJSON() ([]byte, error) { 137 if u.i == nil { // Necessary since default Uint initialization has i.i as nil 138 u.i = new(big.Int) 139 } 140 return marshalJSON(u.i) 141 } 142 143 // UnmarshalJSON defines custom decoding scheme 144 func (u *Uint) UnmarshalJSON(bz []byte) error { 145 if u.i == nil { // Necessary since default Uint initialization has i.i as nil 146 u.i = new(big.Int) 147 } 148 return unmarshalJSON(u.i, bz) 149 } 150 151 // Marshal implements the gogo proto custom type interface. 152 func (u Uint) Marshal() ([]byte, error) { 153 if u.i == nil { 154 u.i = new(big.Int) 155 } 156 return u.i.MarshalText() 157 } 158 159 // MarshalTo implements the gogo proto custom type interface. 160 func (u *Uint) MarshalTo(data []byte) (n int, err error) { 161 if u.i == nil { 162 u.i = new(big.Int) 163 } 164 if u.i.BitLen() == 0 { // The value 0 165 copy(data, []byte{0x30}) 166 return 1, nil 167 } 168 169 bz, err := u.Marshal() 170 if err != nil { 171 return 0, err 172 } 173 174 copy(data, bz) 175 return len(bz), nil 176 } 177 178 // Unmarshal implements the gogo proto custom type interface. 179 func (u *Uint) Unmarshal(data []byte) error { 180 if len(data) == 0 { 181 u = nil 182 return nil 183 } 184 185 if u.i == nil { 186 u.i = new(big.Int) 187 } 188 189 if err := u.i.UnmarshalText(data); err != nil { 190 return err 191 } 192 193 if u.i.BitLen() > maxBitLen { 194 return fmt.Errorf("integer out of range; got: %d, max: %d", u.i.BitLen(), maxBitLen) 195 } 196 197 return nil 198 } 199 200 // Size implements the gogo proto custom type interface. 201 func (u *Uint) Size() int { 202 bz, _ := u.Marshal() 203 return len(bz) 204 } 205 206 // Override Amino binary serialization by proxying to protobuf. 207 func (u Uint) MarshalAmino() ([]byte, error) { return u.Marshal() } 208 func (u *Uint) UnmarshalAmino(bz []byte) error { return u.Unmarshal(bz) } 209 210 // UintOverflow returns true if a given unsigned integer overflows and false 211 // otherwise. 212 func UintOverflow(i *big.Int) error { 213 if i.Sign() < 0 { 214 return errors.New("non-positive integer") 215 } 216 if i.BitLen() > 256 { 217 return fmt.Errorf("bit length %d greater than 256", i.BitLen()) 218 } 219 return nil 220 } 221 222 // ParseUint reads a string-encoded Uint value and return a Uint. 223 func ParseUint(s string) (Uint, error) { 224 i, ok := new(big.Int).SetString(s, 0) 225 if !ok { 226 return Uint{}, fmt.Errorf("cannot convert %q to big.Int", s) 227 } 228 return checkNewUint(i) 229 } 230 231 func checkNewUint(i *big.Int) (Uint, error) { 232 if err := UintOverflow(i); err != nil { 233 return Uint{}, err 234 } 235 return Uint{i}, nil 236 } 237 238 // RelativePow raises x to the power of n, where x (and the result, z) are scaled by factor b 239 // for example, RelativePow(210, 2, 100) = 441 (2.1^2 = 4.41) 240 func RelativePow(x Uint, n Uint, b Uint) (z Uint) { 241 if x.IsZero() { 242 if n.IsZero() { 243 z = b // 0^0 = 1 244 return 245 } 246 z = ZeroUint() // otherwise 0^a = 0 247 return 248 } 249 250 z = x 251 if n.Mod(NewUint(2)).Equal(ZeroUint()) { 252 z = b 253 } 254 255 halfOfB := b.Quo(NewUint(2)) 256 n = n.Quo(NewUint(2)) 257 258 for n.GT(ZeroUint()) { 259 xSquared := x.Mul(x) 260 xSquaredRounded := xSquared.Add(halfOfB) 261 262 x = xSquaredRounded.Quo(b) 263 264 if n.Mod(NewUint(2)).Equal(OneUint()) { 265 zx := z.Mul(x) 266 zxRounded := zx.Add(halfOfB) 267 z = zxRounded.Quo(b) 268 } 269 n = n.Quo(NewUint(2)) 270 } 271 return z 272 }