github.com/igggame/nebulas-go@v2.1.0+incompatible/util/uint128.go (about) 1 package util 2 3 import ( 4 "errors" 5 "math/big" 6 ) 7 8 const ( 9 // Uint128Bytes defines the number of bytes for Uint128 type. 10 Uint128Bytes = 16 11 12 // Uint128Bits defines the number of bits for Uint128 type. 13 Uint128Bits = 128 14 ) 15 16 var ( 17 // ErrUint128Overflow indicates the value is greater than uint128 maximum value 2^128. 18 ErrUint128Overflow = errors.New("uint128: overflow") 19 20 // ErrUint128Underflow indicates the value is smaller then uint128 minimum value 0. 21 ErrUint128Underflow = errors.New("uint128: underflow") 22 23 // ErrUint128InvalidBytesSize indicates the bytes size is not equal to Uint128Bytes. 24 ErrUint128InvalidBytesSize = errors.New("uint128: invalid bytes") 25 26 // ErrUint128InvalidString indicates the string is not valid when converted to uin128. 27 ErrUint128InvalidString = errors.New("uint128: invalid string to uint128") 28 ) 29 30 // Uint128 defines uint128 type, based on big.Int. 31 // 32 // For arithmetic operations, use uint128.Int.Add()/Sub()/Mul()/Div()/etc. 33 // For example, u1.Add(u1.Int, u2.Int) sets u1 to u1 + u2. 34 type Uint128 struct { 35 value *big.Int 36 } 37 38 // Validate returns error if u is not a valid uint128, otherwise returns nil. 39 func (u *Uint128) Validate() error { 40 if u.value.Sign() < 0 { 41 return ErrUint128Underflow 42 } 43 if u.value.BitLen() > Uint128Bits { 44 return ErrUint128Overflow 45 } 46 return nil 47 } 48 49 // NewUint128 returns a new Uint128 struct with default value. 50 func NewUint128() *Uint128 { 51 return &Uint128{big.NewInt(0)} 52 } 53 54 // NewUint128FromString returns a new Uint128 struct with given value and have a check. 55 func NewUint128FromString(str string) (*Uint128, error) { 56 big := new(big.Int) 57 _, success := big.SetString(str, 10) 58 if !success { 59 return nil, ErrUint128InvalidString 60 } 61 if err := (&Uint128{big}).Validate(); nil != err { 62 return nil, err 63 } 64 return &Uint128{big}, nil 65 } 66 67 // NewUint128FromUint returns a new Uint128 with given value 68 func NewUint128FromUint(i uint64) *Uint128 { 69 obj := NewUint128() 70 obj.value.SetUint64(i) 71 return obj 72 } 73 74 // NewUint128FromInt returns a new Uint128 struct with given value and have a check. 75 func NewUint128FromInt(i int64) (*Uint128, error) { 76 obj := &Uint128{big.NewInt(i)} 77 if err := obj.Validate(); nil != err { 78 return nil, err 79 } 80 return obj, nil 81 } 82 83 // NewUint128FromBigInt returns a new Uint128 struct with given value and have a check. 84 func NewUint128FromBigInt(i *big.Int) (*Uint128, error) { 85 obj := &Uint128{i} 86 if err := obj.Validate(); nil != err { 87 return nil, err 88 } 89 return obj, nil 90 } 91 92 // NewUint128FromFixedSizeBytes returns a new Uint128 struct with given fixed size byte array. 93 func NewUint128FromFixedSizeBytes(bytes [16]byte) *Uint128 { 94 u := NewUint128() 95 return u.FromFixedSizeBytes(bytes) 96 } 97 98 // NewUint128FromFixedSizeByteSlice returns a new Uint128 struct with given fixed size byte slice. 99 func NewUint128FromFixedSizeByteSlice(bytes []byte) (*Uint128, error) { 100 u := NewUint128() 101 return u.FromFixedSizeByteSlice(bytes) 102 } 103 104 // Uint128Zero zero of uint128 105 func Uint128Zero() *Uint128 { 106 return NewUint128FromUint(0) 107 } 108 109 // ToFixedSizeBytes converts Uint128 to Big-Endian fixed size bytes. 110 func (u *Uint128) ToFixedSizeBytes() ([16]byte, error) { 111 var res [16]byte 112 if err := u.Validate(); err != nil { 113 return res, err 114 } 115 bs := u.value.Bytes() 116 l := len(bs) 117 if l == 0 { 118 return res, nil 119 } 120 idx := Uint128Bytes - len(bs) 121 if idx < Uint128Bytes { 122 copy(res[idx:], bs) 123 } 124 return res, nil 125 } 126 127 // ToFixedSizeByteSlice converts Uint128 to Big-Endian fixed size byte slice. 128 func (u *Uint128) ToFixedSizeByteSlice() ([]byte, error) { 129 bytes, err := u.ToFixedSizeBytes() 130 return bytes[:], err 131 } 132 133 // String returns the string representation of x. 134 func (u *Uint128) String() string { 135 return u.value.Text(10) 136 } 137 138 // FromFixedSizeBytes converts Big-Endian fixed size bytes to Uint128. 139 func (u *Uint128) FromFixedSizeBytes(bytes [16]byte) *Uint128 { 140 u.FromFixedSizeByteSlice(bytes[:]) 141 return u 142 } 143 144 // FromFixedSizeByteSlice converts Big-Endian fixed size bytes to Uint128. 145 func (u *Uint128) FromFixedSizeByteSlice(bytes []byte) (*Uint128, error) { 146 if len(bytes) != Uint128Bytes { 147 return nil, ErrUint128InvalidBytesSize 148 } 149 i := 0 150 for ; i < Uint128Bytes; i++ { 151 if bytes[i] != 0 { 152 break 153 } 154 } 155 if i < Uint128Bytes { 156 u.value.SetBytes(bytes[i:]) 157 } else { 158 u.value.SetUint64(0) 159 } 160 return u, nil 161 } 162 163 // Uint64 returns the uint64 representation of x. 164 // If x cannot be represented in a uint64, the result is undefined. 165 func (u *Uint128) Uint64() uint64 { 166 return u.value.Uint64() 167 } 168 169 //Add returns u + x 170 func (u *Uint128) Add(x *Uint128) (*Uint128, error) { 171 obj := &Uint128{NewUint128().value.Add(u.value, x.value)} 172 if err := obj.Validate(); nil != err { 173 return u, err 174 } 175 return obj, nil 176 } 177 178 //Sub returns u - x 179 func (u *Uint128) Sub(x *Uint128) (*Uint128, error) { 180 obj := &Uint128{NewUint128().value.Sub(u.value, x.value)} 181 if err := obj.Validate(); nil != err { 182 return u, err 183 } 184 return obj, nil 185 } 186 187 //Mul returns u * x 188 func (u *Uint128) Mul(x *Uint128) (*Uint128, error) { 189 obj := &Uint128{NewUint128().value.Mul(u.value, x.value)} 190 if err := obj.Validate(); nil != err { 191 return u, err 192 } 193 return obj, nil 194 } 195 196 //Div returns u / x 197 func (u *Uint128) Div(x *Uint128) (*Uint128, error) { 198 obj := &Uint128{NewUint128().value.Div(u.value, x.value)} 199 if err := obj.Validate(); nil != err { 200 return u, err 201 } 202 return obj, nil 203 } 204 205 //Exp returns u^x 206 func (u *Uint128) Exp(x *Uint128) (*Uint128, error) { 207 obj := &Uint128{NewUint128().value.Exp(u.value, x.value, nil)} 208 if err := obj.Validate(); nil != err { 209 return u, err 210 } 211 return obj, nil 212 } 213 214 //DeepCopy returns a deep copy of u 215 func (u *Uint128) DeepCopy() *Uint128 { 216 z := new(big.Int) 217 z.Set(u.value) 218 return &Uint128{z} 219 } 220 221 // Cmp compares u and x and returns: 222 // 223 // -1 if u < x 224 // 0 if u == x 225 // +1 if u > x 226 func (u *Uint128) Cmp(x *Uint128) int { 227 return u.value.Cmp(x.value) 228 } 229 230 //Bytes absolute value of u as a big-endian byte slice. 231 func (u *Uint128) Bytes() []byte { 232 return u.value.Bytes() 233 }