github.com/ontio/ontology@v1.14.4/vm/neovm/types/int_value.go (about) 1 /* 2 * Copyright (C) 2018 The ontology Authors 3 * This file is part of The ontology library. 4 * 5 * The ontology is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * The ontology is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with The ontology. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 package types 20 21 import ( 22 "math" 23 "math/big" 24 25 "github.com/JohnCGriffin/overflow" 26 "github.com/ontio/ontology/common" 27 "github.com/ontio/ontology/vm/neovm/constants" 28 "github.com/ontio/ontology/vm/neovm/errors" 29 ) 30 31 type IntValue struct { 32 isbig bool 33 integer int64 34 bigint *big.Int 35 } 36 37 func (self IntValue) Rsh(other IntValue) (result IntValue, err error) { 38 var val uint64 39 if !other.isbig { 40 if other.integer < 0 { 41 err = errors.ERR_SHIFT_BY_NEG 42 return 43 } 44 val = uint64(other.integer) 45 } else { 46 if !other.bigint.IsUint64() { 47 return IntValue{}, errors.ERR_SHIFT_BY_NEG 48 } 49 val = other.bigint.Uint64() 50 } 51 52 if val > constants.MAX_INT_SIZE*8 { 53 // IntValue is enforced to not exceed this size, so return 0 directly 54 // (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1) reference from big.Int 55 // (-x) >> s == -(0 + 1) == -1 56 if self.Sign() < 0 { 57 result = IntValFromInt(-1) 58 } 59 return 60 } 61 62 left := big.NewInt(self.integer) 63 if self.isbig { 64 left.Set(self.bigint) 65 } 66 67 left.Rsh(left, uint(val)) 68 69 return IntValFromBigInt(left) 70 } 71 72 func (self IntValue) Lsh(other IntValue) (result IntValue, err error) { 73 var val uint64 74 if !other.isbig { 75 if other.integer < 0 { 76 err = errors.ERR_SHIFT_BY_NEG 77 return 78 } 79 val = uint64(other.integer) 80 } else { 81 if !other.bigint.IsUint64() { 82 return IntValue{}, errors.ERR_SHIFT_BY_NEG 83 } 84 val = other.bigint.Uint64() 85 } 86 87 if val > constants.MAX_INT_SIZE*8 { 88 err = errors.ERR_OVER_MAX_BIGINTEGER_SIZE 89 return 90 } 91 92 left := big.NewInt(self.integer) 93 if self.isbig { 94 left.Set(self.bigint) 95 } 96 97 left.Lsh(left, uint(val)) 98 99 return IntValFromBigInt(left) 100 } 101 102 func IntValFromBigInt(val *big.Int) (result IntValue, err error) { 103 if val == nil { 104 err = errors.ERR_BAD_VALUE 105 return 106 } 107 // todo : check compatibility 108 if len(val.Bytes()) > constants.MAX_INT_SIZE { 109 err = errors.ERR_OVER_MAX_BIGINTEGER_SIZE 110 } 111 112 if val.IsInt64() { 113 result.isbig = false 114 result.integer = val.Int64() 115 } else { 116 result.isbig = true 117 result.bigint = val 118 } 119 120 return 121 } 122 123 func IntValFromNeoBytes(val []byte) (IntValue, error) { 124 value := common.BigIntFromNeoBytes(val) 125 return IntValFromBigInt(value) 126 } 127 128 func (self *IntValue) ToNeoBytes() []byte { 129 val := self.bigint 130 if !self.isbig { 131 val = big.NewInt(self.integer) 132 } 133 value := common.BigIntToNeoBytes(val) 134 return value 135 } 136 137 func IntValFromInt(val int64) IntValue { 138 return IntValue{isbig: false, integer: val} 139 } 140 141 func (self *IntValue) IsZero() bool { 142 if self.isbig { 143 return self.bigint.Sign() == 0 144 } else { 145 return self.integer == 0 146 } 147 } 148 149 func (self *IntValue) Sign() int { 150 if self.isbig { 151 return self.bigint.Sign() 152 } else { 153 if self.integer < 0 { 154 return -1 155 } else if self.integer == 0 { 156 return 0 157 } else { 158 return 1 159 } 160 } 161 } 162 163 func (self IntValue) Max(other IntValue) (IntValue, error) { 164 return self.intOp(other, func(a, b int64) (int64, bool) { 165 if a < b { 166 return b, true 167 } 168 return a, true 169 }, func(a, b *big.Int) (IntValue, error) { 170 result := new(big.Int) 171 c := a.Cmp(b) 172 if c <= 0 { 173 result.Set(b) 174 } else { 175 result.Set(a) 176 } 177 return IntValFromBigInt(result) 178 }) 179 } 180 181 func (self IntValue) Min(other IntValue) (IntValue, error) { 182 return self.intOp(other, func(a, b int64) (int64, bool) { 183 if a < b { 184 return a, true 185 } 186 return b, true 187 }, func(a, b *big.Int) (IntValue, error) { 188 result := new(big.Int) 189 c := a.Cmp(b) 190 if c <= 0 { 191 result.Set(a) 192 } else { 193 result.Set(b) 194 } 195 return IntValFromBigInt(result) 196 }) 197 } 198 199 func (self IntValue) Xor(other IntValue) (IntValue, error) { 200 return self.intOp(other, func(a, b int64) (int64, bool) { 201 return a ^ b, true 202 }, func(a, b *big.Int) (IntValue, error) { 203 return IntValFromBigInt(new(big.Int).Xor(a, b)) 204 }) 205 } 206 207 func (self IntValue) And(other IntValue) (IntValue, error) { 208 return self.intOp(other, func(a, b int64) (int64, bool) { 209 return a & b, true 210 }, func(a, b *big.Int) (IntValue, error) { 211 return IntValFromBigInt(new(big.Int).And(a, b)) 212 }) 213 } 214 215 func (self IntValue) Or(other IntValue) (IntValue, error) { 216 return self.intOp(other, func(a, b int64) (int64, bool) { 217 return a | b, true 218 }, func(a, b *big.Int) (IntValue, error) { 219 return IntValFromBigInt(new(big.Int).Or(a, b)) 220 }) 221 } 222 223 func (self IntValue) Cmp(other IntValue) int { 224 if !self.isbig && !other.isbig { 225 if self.integer < other.integer { 226 return -1 227 } else if self.integer == other.integer { 228 return 0 229 } else { 230 return 1 231 } 232 } 233 var left, right *big.Int 234 if !self.isbig { 235 left = big.NewInt(self.integer) 236 } else { 237 left = self.bigint 238 } 239 if !other.isbig { 240 right = big.NewInt(other.integer) 241 } else { 242 right = other.bigint 243 } 244 245 return left.Cmp(right) 246 } 247 248 func (self IntValue) Not() (val IntValue) { 249 if self.isbig { 250 val.isbig = true 251 val.bigint = big.NewInt(0) 252 val.bigint.Not(self.bigint) 253 } else { 254 val.integer = ^self.integer 255 } 256 return 257 } 258 259 func (self IntValue) Abs() (val IntValue) { 260 if self.isbig { 261 val.isbig = true 262 val.bigint = big.NewInt(0) 263 val.bigint.Abs(self.bigint) 264 } else { 265 if self.integer == math.MinInt64 { 266 val.isbig = true 267 val.bigint = big.NewInt(self.integer) 268 val.bigint.Abs(val.bigint) 269 } else if self.integer < 0 { 270 val.integer = -self.integer 271 } else { 272 val.integer = self.integer 273 } 274 } 275 return 276 } 277 278 // todo: check negative value with big.Int 279 func (self IntValue) Mod(other IntValue) (IntValue, error) { 280 if other.IsZero() { 281 return IntValue{}, errors.ERR_DIV_MOD_BY_ZERO 282 } 283 return self.intOp(other, func(a, b int64) (int64, bool) { 284 return a % b, true 285 }, func(a, b *big.Int) (IntValue, error) { 286 return IntValFromBigInt(new(big.Int).Rem(a, b)) 287 }) 288 } 289 290 // todo: check negative value with big.Int 291 func (self IntValue) Div(other IntValue) (IntValue, error) { 292 if other.IsZero() { 293 return IntValue{}, errors.ERR_DIV_MOD_BY_ZERO 294 } 295 return self.intOp(other, func(a, b int64) (int64, bool) { 296 return a / b, true 297 }, func(a, b *big.Int) (IntValue, error) { 298 return IntValFromBigInt(new(big.Int).Quo(a, b)) 299 }) 300 } 301 302 func (self IntValue) Mul(other IntValue) (IntValue, error) { 303 return self.intOp(other, overflow.Mul64, func(a, b *big.Int) (IntValue, error) { 304 return IntValFromBigInt(new(big.Int).Mul(a, b)) 305 }) 306 } 307 308 func (self IntValue) Add(other IntValue) (IntValue, error) { 309 return self.intOp(other, overflow.Add64, func(a, b *big.Int) (IntValue, error) { 310 return IntValFromBigInt(new(big.Int).Add(a, b)) 311 }) 312 } 313 314 func (self IntValue) Sub(other IntValue) (IntValue, error) { 315 return self.intOp(other, overflow.Sub64, func(a, b *big.Int) (IntValue, error) { 316 return IntValFromBigInt(new(big.Int).Sub(a, b)) 317 }) 318 } 319 320 type overflowFn func(a, b int64) (result int64, ok bool) 321 type bigintFn func(a, b *big.Int) (IntValue, error) 322 323 func (self IntValue) intOp(other IntValue, littleintFunc overflowFn, bigintFunc bigintFn) (IntValue, error) { 324 if !self.isbig && !other.isbig { 325 val, ok := littleintFunc(self.integer, other.integer) 326 if ok { 327 return IntValFromInt(val), nil 328 } 329 } 330 var left, right *big.Int 331 if !self.isbig { 332 left = big.NewInt(self.integer) 333 } else { 334 left = self.bigint 335 } 336 if !other.isbig { 337 right = big.NewInt(other.integer) 338 } else { 339 right = other.bigint 340 } 341 342 return bigintFunc(left, right) 343 }